发送不同类型的数据,在验证之前修改它以适应?

时间:2015-04-09 15:47:19

标签: python django rest django-rest-framework

我没有找到任何可以解决问题的解决方案。虽然它可能不是通过休息对流来接收一种类型的数据并发送回其他类型。让我们说这样的事情对我来说是实用的。

我有Seri​​alizer,它结合了两个以上的序列化程序。我看来的问题是articles中的相关keywordsArticleSerializer字段,准确地说是插入实际上是相关对象的两个字段。启动序列化程序代码如下所示:

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')

当我像这样的形式发送像dicts数组这样的关键字时:

.....
keywords:[
    {id:1},
    {id:2}
]
......

他们得救了,一切都没有问题。但我的想法是在前端有一个速记灵魂,并发送只代表ID的整数数组。当我尝试这样做时:

.....
keywords:[1,2]
......

我在休息时得到以下回应:

{
"keywords": [
    {
        "non_field_errors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    },
    {
        "non_field_errors": [
            "Invalid data. Expected a dictionary, but got int."
        ]
    },
 }

我的想法是覆盖它以进一步发送视频 perform_update perform_create 方法中的dicts或某些内容,但从程序角度来看已经太晚了。

我认为最好的方法是在验证之前捕获这些值并将整数列表转换为dicts列表并在此过程中进一步传递,但我找不到这样做的方法。这有可能,究竟是怎么回事?或者我应该编写自定义验证吗?

1 个答案:

答案 0 :(得分:0)

  

我的想法是覆盖它以进一步发送像dicts或视图中的perform_update和perform_create metods,但从程序角度来看已经太晚了。

你说得对,在那里做太晚了。如果您查看DRF中的代码(在mixins.py中),您会看到在.is_valid().perform_create()之前调用.perform_update()

所以,就我看来,你有两种选择:

  1. 在您的视图中,您覆盖.post().put()方法,并在调用.is_valid()之前对整数列表进行修改。这将是这样的:

    def post(self, request, *args, **kwargs):
        // HERE transform your data as you wish
        return self.create(request, *args, **kwargs)
    
  2. 第二个想法是不传递关键字的嵌套序列化程序,只让DRF处理反序列化。这意味着您可以删除行keywords = ArticleKeywordsSerializer(...),当您收到json时,DRF将自动期望一个整数列表(名为articlekeywords_set)。但是,在这种情况下,您将需要不同的GET和POST序列化程序(假设您要发送嵌套对象)。

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