Python 发送不同类型的数据,在验证之前对其进行修改以适应?

Python 发送不同类型的数据,在验证之前对其进行修改以适应?,python,django,rest,django-rest-framework,Python,Django,Rest,Django Rest Framework,我没有找到解决问题的办法。尽管接收一种类型的数据并发回另一种类型的数据可能不是静止对流。比如说,像这样的事情对我来说是可行的 我有一个序列化程序,它组合了另外两个序列化程序。在我看来,问题在于ArticleSerializer中的相关文章和关键字字段,确切地说是插入这两个实际上是相关对象的字段。要启动序列化程序的代码,如下所示: class ArticleAuthorsSerializer(serializers.ModelSerializer): related_id = serial

我没有找到解决问题的办法。尽管接收一种类型的数据并发回另一种类型的数据可能不是静止对流。比如说,像这样的事情对我来说是可行的

我有一个序列化程序,它组合了另外两个序列化程序。在我看来,问题在于ArticleSerializer中的相关文章和关键字字段,确切地说是插入这两个实际上是相关对象的字段。要启动序列化程序的代码,如下所示:

class ArticleAuthorsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='author.id')
    first_name = serializers.ReadOnlyField(source='author.first_name')
    last_name = serializers.ReadOnlyField(source='author.last_name')
    full_name = serializers.ReadOnlyField(source='author.full_name')


    class Meta:
        model = ArticleAuthors
        fields = ('related_id', 'related_order', 'id', 'first_name', 'last_name', 'full_name', )
        list_serializer_class = SelectRelatedListSerializer.factory(['author'])

class ArticleKeywordsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='keyword.id')
    name = serializers.ReadOnlyField(source='keyword.name')
    slug = serializers.ReadOnlyField(source='keyword.slug')

    class Meta:
        model = ArticleKeywords
        fields = ('related_id', 'related_order', 'id', 'name', 'slug', )
        list_serializer_class = SelectRelatedListSerializer.factory(['keyword'])


class ArticleSerializer(serializers.ModelSerializer):
    user_created = UserSerializer(read_only=True)
    authors = ArticleAuthorsSerializer(source='articleauthors_set', many=True, read_only=False, )
    keywords = ArticleKeywordsSerializer(source='articlekeywords_set', many=True, read_only=False, )


    class Meta:
        model = Article
        fields = ('id', 'title', 'slug', 'intro', 'content', 'date_created',
        'date_published', 'date_modified', 'state', 'user_created',
        'authors', 'keywords', 'url')
.....
keywords:[
    {id:1},
    {id:2}
]
......
def post(self, request, *args, **kwargs):
    // HERE transform your data as you wish
    return self.create(request, *args, **kwargs)
例如,当我以如下形式发送dicts数组之类的关键字时:

class ArticleAuthorsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='author.id')
    first_name = serializers.ReadOnlyField(source='author.first_name')
    last_name = serializers.ReadOnlyField(source='author.last_name')
    full_name = serializers.ReadOnlyField(source='author.full_name')


    class Meta:
        model = ArticleAuthors
        fields = ('related_id', 'related_order', 'id', 'first_name', 'last_name', 'full_name', )
        list_serializer_class = SelectRelatedListSerializer.factory(['author'])

class ArticleKeywordsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='keyword.id')
    name = serializers.ReadOnlyField(source='keyword.name')
    slug = serializers.ReadOnlyField(source='keyword.slug')

    class Meta:
        model = ArticleKeywords
        fields = ('related_id', 'related_order', 'id', 'name', 'slug', )
        list_serializer_class = SelectRelatedListSerializer.factory(['keyword'])


class ArticleSerializer(serializers.ModelSerializer):
    user_created = UserSerializer(read_only=True)
    authors = ArticleAuthorsSerializer(source='articleauthors_set', many=True, read_only=False, )
    keywords = ArticleKeywordsSerializer(source='articlekeywords_set', many=True, read_only=False, )


    class Meta:
        model = Article
        fields = ('id', 'title', 'slug', 'intro', 'content', 'date_created',
        'date_published', 'date_modified', 'state', 'user_created',
        'authors', 'keywords', 'url')
.....
keywords:[
    {id:1},
    {id:2}
]
......
def post(self, request, *args, **kwargs):
    // HERE transform your data as you wish
    return self.create(request, *args, **kwargs)
它们已保存,所有内容都已更新,没有问题。但我的想法是在前端有一个速记解,只发送代表ID的整数数组。当我尝试这样做时:

.....
keywords:[1,2]
......
我在rest gui中得到以下响应:

{
"keywords": [
    {
        "non_field_errors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    },
    {
        "non_field_errors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    },
 }
我的想法是覆盖它,以发送更多的命令,如dicts或视图中的其他内容,执行更新和创建方法,但从程序的角度来看,这已经太晚了

我认为最好的方法是在验证之前捕获这些值,将整数列表转换为dict列表,并在过程中进一步传递,但我找不到这样做的方法。这可能吗?具体如何?还是应该编写自定义验证

我的想法是覆盖它,以发送更多的命令,如dicts或视图中的其他内容,执行更新和创建方法,但从程序的角度来看,这已经太晚了

你说得对,在那里做已经太晚了。如果查看中DRF中的代码,您将看到在调用.is\u valid之前调用了.perform\u create或.perform\u update

在我看来,你有两个选择:

在您的视图中,您重写了.post和.put方法,并且在调用.is\u之前对整数列表进行了修改。这将是这样的:

class ArticleAuthorsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='author.id')
    first_name = serializers.ReadOnlyField(source='author.first_name')
    last_name = serializers.ReadOnlyField(source='author.last_name')
    full_name = serializers.ReadOnlyField(source='author.full_name')


    class Meta:
        model = ArticleAuthors
        fields = ('related_id', 'related_order', 'id', 'first_name', 'last_name', 'full_name', )
        list_serializer_class = SelectRelatedListSerializer.factory(['author'])

class ArticleKeywordsSerializer(serializers.ModelSerializer):
    related_id = serializers.ReadOnlyField(source='id')
    related_order = serializers.IntegerField(source="order", required=False)

    id = serializers.ReadOnlyField(source='keyword.id')
    name = serializers.ReadOnlyField(source='keyword.name')
    slug = serializers.ReadOnlyField(source='keyword.slug')

    class Meta:
        model = ArticleKeywords
        fields = ('related_id', 'related_order', 'id', 'name', 'slug', )
        list_serializer_class = SelectRelatedListSerializer.factory(['keyword'])


class ArticleSerializer(serializers.ModelSerializer):
    user_created = UserSerializer(read_only=True)
    authors = ArticleAuthorsSerializer(source='articleauthors_set', many=True, read_only=False, )
    keywords = ArticleKeywordsSerializer(source='articlekeywords_set', many=True, read_only=False, )


    class Meta:
        model = Article
        fields = ('id', 'title', 'slug', 'intro', 'content', 'date_created',
        'date_published', 'date_modified', 'state', 'user_created',
        'authors', 'keywords', 'url')
.....
keywords:[
    {id:1},
    {id:2}
]
......
def post(self, request, *args, **kwargs):
    // HERE transform your data as you wish
    return self.create(request, *args, **kwargs)
第二个想法是不要为关键字传递嵌套序列化程序,而只让DRF处理反序列化。这意味着您可以删除行关键字=ArticleKeywordsSerializer。。。当您收到json时,DRF将自动期望一个名为articlekeywords\u set的整数列表。但是,在这种情况下,假设要发送嵌套对象,则GET和POST需要不同的序列化程序


不要忘记,对于第一个选项,您仍然必须重写序列化程序上的.create和.update方法,因为DRF不再支持可写嵌套序列化。请参阅。

谢谢您的建议。我必须抓紧时间尝试你的建议,我会让你知道结果: