Nus*_*chk 1 python django django-rest-framework
在使用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
Run Code Online (Sandbox Code Playgroud)
(我省略了perform_create中的代码,因为它与问题无关).
现在,传递一个普通的dict作为数据参数工作正常:
ser = ParentSerializer(data=dict(field_a=3))
ser.is_valid(raise_exception=True)
Run Code Online (Sandbox Code Playgroud)
但是传递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.']}}
Run Code Online (Sandbox Code Playgroud)
在实际的网站上,API得到一个正常的字典,因此工作正常.但是在测试期间,使用类似的东西client.post('url', data=dict(field_a=3))会导致QueryDict传递给视图,因此无法工作.
所以我的问题是:QueryDict和普通字典有什么区别?或者我是以错误的方式接近这个?
DRF定义了多个解析器类,用于解析具有不同媒体类型的请求内容.
request.data通常是一个QueryDict或一个普通的字典,具体取决于用于解析请求内容的解析器.
它解析JSON请求内容,即内容为.media_typeas application/json.
它解析HTML表单内容.这里request.data填充了QueryDict一些数据.这些都.media_type为application/x-www-form-urlencoded.
它解析支持文件上传的多部分HTML表单内容.在这里,两者request.data都填充了一个QueryDict.这些都
.media_type为multipart/form-data.
它解析原始文件上传内容.该request.data属性是一个file包含上传文件的单个字典的字典.
DRF如何确定解析器?
当DRF访问时request.data,它会检查Content-Type传入请求上的标头,然后确定使用哪个解析器来解析请求内容.
您需要Content-Type在发送数据时设置标头,否则它将使用multipart或form解析器来解析请求内容并为您提供QueryDictin request.data而不是字典.
根据DRF文档,
如果您未设置内容类型,则大多数客户端将默认使用
'application/x-www-form-urlencoded',这可能不是您想要的.
因此,当发送json编码数据时,还要将Content-Type标头设置为application/json,然后它将按预期工作.
为什么request.data有时候QueryDict,有时候dict?
这样做是因为不同的编码具有不同的数据结构和属性.
例如,表单数据是支持相同值的多个键的编码,而json不支持.
同样在JSON数据的情况下,request.DATA可能根本不是dict,它可以是列表或任何其他json原语.
查看此Google网上论坛帖子,了解相同内容.
你需要做什么?
您可以format='json'在测试时添加POSTing将设置内容类型的数据以及正确序列化数据.
client.post('url', format='json', data=dict(field_a=3))
Run Code Online (Sandbox Code Playgroud)
您还可以使用content-type参数发送JSON编码的内容.
client.post('url', json.dumps(dict(field_a=3)), content_type='application/json')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1751 次 |
| 最近记录: |