序列化可选嵌套结构:QueryDict和普通dict的区别?

2024-10-01 07:38:58 发布

您现在位置:Python中文网/ 问答频道 /正文

当我用django rest编写嵌套结构,然后尝试使用django rest的测试客户机测试它们时,我遇到了一些奇怪的行为。嵌套的子对象应该是可选的。在

下面是一个序列化程序示例:

from rest_framework import serializers

class OptionalChildSerializer(serializers.Serializer):
    field_b = serializers.IntegerField()
    field_c = serializers.IntegerField()

    class Meta:
        fields = ('field_b', 'field_c', )

class ParentSerializer(serializers.Serializer):
    field_a = serializers.IntegerField()
    child = OptionalChildSerializer(required=False, many=False)

    class Meta:
        fields = ('a', 'child',)

    def perform_create(self, serializer):
        # TODO: create nested object.
        pass

(我省略了perform\u create中的代码,因为它与问题无关)。在

现在,传递一个普通的dict作为数据参数就可以了:

^{pr2}$

但是,传递一个QueryDict将失败:

from django.http import QueryDict
ser = ParentSerializer(data=QueryDict("field_a=3"))
ser.is_valid(raise_exception=True)

ValidationError: {'child': {'field_b': [u'This field is required.'], 'field_c': [u'This field is required.']}}

在实际的web站点上,API得到一个正常的dict,因此可以正常工作。然而,在测试期间,使用client.post('url', data=dict(field_a=3))之类的东西将导致一个QueryDict被传递到视图,因此无法工作。在

所以我的问题是:QueryDict和普通dict有什么区别?还是我走错了路?在


Tags: djangofromimportrestchildfieldiscreate
2条回答

django rest测试客户机不会自动将数据序列化为json,而是使用multipart/form,这将导致QueryDict。在

但是,有一个格式选项,描述为in the docs。以下测试代码工作正常:

client.post('url', format='json', data=dict(field_a=3))

我仍然对普通dict和QueryDict之间不同的序列化程序行为感到困惑,尽管。。。在

谢谢拉杰什给我指出了正确的方向!在

DRF定义了多个解析器类,用于解析具有不同媒体类型的请求内容。

request.data通常是QueryDict或普通字典,这取决于用于解析请求内容的解析器。在

  • JSONParser:

它解析JSON请求内容,即带有.media_type的内容为application/json。在

  • FormParser

它解析HTML表单内容。在这里,request.data填充了QueryDict的数据。这些数据的.media_typeapplication/x-www-form-urlencoded。在

  • MultiPartParser

它解析支持文件上传的多部分HTML表单内容。这里,两个request.data都填充了QueryDict。这些有 .media_type作为multipart/form-data。在

  • FileUploadParser

它解析原始文件上载内容。request.data属性是一个包含上载文件的单键file的字典。在

DRF determines如何解析?

当DRF访问request.data时,它检查传入请求的Content-Type报头,然后确定使用哪个解析器来解析请求内容。在

在发送数据时,您需要设置Content-Type头,否则它将使用多部分或表单解析器解析请求内容,并在request.data中给您一个QueryDict,而不是字典。在

根据DRF文件

^{bq}$

因此,在发送json编码的数据时,还应将Content-Type头设置为application/json,然后它将按预期工作。在

为什么请求数据有时是QueryDict,有时是{}?

这样做是因为不同的编码具有不同的数据结构和属性。

例如,表单数据是一种编码,它支持相同值的多个键,而json不支持这一点。在

同样,对于JSON数据,request.DATA可能根本不是dict,它可以是一个列表或任何其他JSON原语。在

看看这个Google Groups thread差不多。在

你需要做什么?

您可以在测试中添加format='json',当POSTing的数据将设置内容类型并正确序列化数据。在

client.post('url', format='json', data=dict(field_a=3))

还可以使用content-type参数发送JSON编码的内容。在

^{pr2}$

相关问题 更多 >