为什么Django HttpRequest(POST)似乎将request.data设置为来自request.body的“data”键的值?

时间:2018-05-03 15:33:58

标签: python django django-rest-framework http-post wsgi

背景

我有一个Django wsgi应用程序,它也使用了django-rest-framework。向我的应用程序发出POST请求,该请求具有包含密钥“data”的JSON有效载荷,例如。

{'meta': {'some': 'stuff'}, 'data': {'other': 'stuff'}}

我注意到WSGIRequest对象(一旦它被初始化,即不是django-rest-framework请求对象),request.body包含完整的有效负载,但request.data包含request的值。体[ '数据']。编写我的应用程序取决于request.data中只存在“data”键值的事实。

我最近将Django从1.6升级到1.11,django-rest-framework从2.3.8升级到3.8.2。较新版本的DRF实现了自己的request.data,而之前只是将它代理到底层的Django请求对象。新实现将request.data设置为已解析的request.body。这使我的应用程序更加突破了。

问题

我在源代码或其他地方找不到request.data应该与request.body不同的任何指示。相反,几个问题似乎理所当然地认为它们是相同的。任何人都可以帮我弄清楚我是否发现了一个错误或者这是否是预期的行为?我的申请是否做出了无根据的假设?

由于

更新

以下是邮递员请求的示例:

POST /api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/execute/?hierarchy=1c0ffee2c0deab00da595101&nowait=true&format=json HTTP/1.1
Host: localhost
Content-Type: application/json
Accept: application/json
Authorization: Basic c3lzYWRtaW46c3lzYWRtaW4=
Cache-Control: no-cache
Postman-Token: 5140e8db-6ffa-e2d2-9791-698030fe6caf

{"data":{"name":"_test","parameters":{"parallel":"false","max_workers":"1"},"rollback_disabled":false,"workflow":[{"method":"add","entity_type":"model","entity":"data/Countries","templates":[{"template":"_test"}],"advanced_find_search_direction":"full_tree"}]},"request_meta":{},"meta":{"references":{"form_href":"/api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/?hierarchy=1c0ffee2c0deab00da595101"}}}

如果我在wsgi.py中调试,可以看到问题:

>>> request.body                                                                                                                              
'{"data":{"name":"_test","parameters":{"parallel":"false","max_workers":"1"},"rollback_disabled":false,"workflow":[{"method":"add","entity_ty 
pe":"model","entity":"data/Countries","templates":[{"template":"_test"}],"advanced_find_search_direction":"full_tree"}]},"request_meta":{},"m 
eta":{"references":{"form_href":"/api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/?hierarchy=1c0ffee2c0deab00da595101"}}}'             
>>> request.data                                                                                                                              
{u'rollback_disabled': False, u'name': u'_test', u'parameters': {u'max_workers': u'1', u'parallel': u'false'}, u'workflow': [{u'templates':   
[{u'template': u'_test'}], u'entity': u'data/Countries', u'method': u'add', u'advanced_find_search_direction': u'full_tree', u'entity_type':  
u'model'}]} 

我可以看到底层的请求对象,行为在这里再次清楚:

>>> request._request.data                                                                                                                     
{u'rollback_disabled': False, u'name': u'_test', u'parameters': {u'max_workers': u'1', u'parallel': u'false'}, u'workflow': [{u'templates':   
[{u'template': u'_test'}], u'entity': u'data/Countries', u'method': u'add', u'advanced_find_search_direction': u'full_tree', u'entity_type':  
u'model'}]}                                                                                                                                   
>>> request.data                                                                                                                              
{u'request_meta': {}, u'meta': {u'references': {u'form_href':                                                                                 
u'/api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/?hierarchy=1c0ffee2c0deab00da595101'}}, u'data': {u'rollback_disabled': False,      
u'name': u'_test', u'parameters': {u'max_workers': u'1', u'parallel': u'false'}, u'workflow': [{u'templates': [{u'template': u'_test'}],      
u'entity': u'data/Countries', u'method': u'add', u'advanced_find_search_direction': u'full_tree', u'entity_type': u'model'}]}}                
>>> request.body                                                                                                                              
'{"data":{"name":"_test","parameters":{"parallel":"false","max_workers":"1"},"rollback_disabled":false,"workflow":[{"method":"add","entity_ty 
pe":"model","entity":"data/Countries","templates":[{"template":"_test"}],"advanced_find_search_direction":"full_tree"}]},"request_meta":{},"m 
eta":{"references":{"form_href":"/api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/?hierarchy=1c0ffee2c0deab00da595101"}}}'             
>>> request._request.body                                                                                                                     
'{"data":{"name":"_test","parameters":{"parallel":"false","max_workers":"1"},"rollback_disabled":false,"workflow":[{"method":"add","entity_ty 
pe":"model","entity":"data/Countries","templates":[{"template":"_test"}],"advanced_find_search_direction":"full_tree"}]},"request_meta":{},"m 
eta":{"references":{"form_href":"/api/data/ProvisioningWorkflow/5aeaf9caa9d1cb000887184f/?hierarchy=1c0ffee2c0deab00da595101"}}}' 

1 个答案:

答案 0 :(得分:0)

我已经回答了我自己的问题。我找到了一个将request.data设置为request.body ['data']的中间件。新版本的DRF在这里有一个命名空间冲突,因为它也设置了request.data,但这是在Django中间件生效后发生的。我覆盖了initialize_request并在访问data属性后手动设置_full_data以解决此问题。不幸的是,改变我的应用程序使用request.data的每个案例都是不切实际的。