Почему кажется, что Django HttpRequest (POST) устанавливает request.data в значение ключа «data» из request.body? - PullRequest
0 голосов
/ 03 мая 2018

Фон

У меня есть приложение Django wsgi, которое также использует django-rest-framework. POST-запрос сделан к моему приложению, у которого есть полезная нагрузка JSON, содержащая ключ "данные", например.

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

Я заметил, что объект WSGIRequest (как только он инициализируется, т. Е. Еще не объект запроса django-rest-framework) имеет request.body, содержащий полную полезную нагрузку, но request.data, содержащий значение запроса. тело [ 'данные']. Моя заявка была написана, чтобы зависеть от того факта, что в 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 голосов
/ 07 мая 2018

Я ответил на свой вопрос. Я нашел часть промежуточного программного обеспечения, которое устанавливало request.data для request.body ['data']. Новая версия DRF имеет конфликт пространства имен, поскольку она также устанавливает request.data, но это происходит после того, как промежуточное программное обеспечение Django вступает в силу. Я переопределил initialize_request и вручную установил _full_data после доступа к свойству данных, чтобы обойти это. К сожалению, нецелесообразно менять каждый случай, когда мое приложение использует request.data.

...