diff --git a/docs/api-guide/requests.md b/docs/api-guide/requests.md index e877c868df..2d75e47ddb 100644 --- a/docs/api-guide/requests.md +++ b/docs/api-guide/requests.md @@ -24,6 +24,7 @@ REST framework's Request objects provide flexible request parsing that allows yo * It includes all parsed content, including *file and non-file* inputs. * It supports parsing the content of HTTP methods other than `POST`, meaning that you can access the content of `PUT` and `PATCH` requests. * It supports REST framework's flexible request parsing, rather than just supporting form data. For example you can handle incoming [JSON data] similarly to how you handle incoming [form data]. +* If the client does not send any data and does not specify form encoding, the value of `.data` is determined by the `DEFAULT_MISSING_DATA` setting. If form encoding is used and no data is sent, `.data` will be an empty Django `QueryDict`. For more details see the [parsers documentation]. diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index d42000260b..680b36176f 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -103,6 +103,13 @@ A view inspector class that will be used for schema generation. Default: `'rest_framework.schemas.openapi.AutoSchema'` +#### DEFAULT_MISSING_DATA + +The value that should be used for `request.data` when the client did not send any data in the request body. This +setting applies only if the client did not send a header indicating form encoding. + +Default: `None` + --- ## Generic view settings diff --git a/rest_framework/request.py b/rest_framework/request.py index 17ceadb08e..b9ddc9553a 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -341,7 +341,7 @@ def _parse(self): if media_type and is_form_media_type(media_type): empty_data = QueryDict('', encoding=self._request._encoding) else: - empty_data = {} + empty_data = api_settings.DEFAULT_MISSING_DATA empty_files = MultiValueDict() return (empty_data, empty_files) diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 9eb4c5653b..a8f63e224a 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -46,6 +46,7 @@ 'DEFAULT_CONTENT_NEGOTIATION_CLASS': 'rest_framework.negotiation.DefaultContentNegotiation', 'DEFAULT_METADATA_CLASS': 'rest_framework.metadata.SimpleMetadata', 'DEFAULT_VERSIONING_CLASS': None, + 'DEFAULT_MISSING_DATA': None, # Generic view behavior 'DEFAULT_PAGINATION_CLASS': None, diff --git a/tests/test_request.py b/tests/test_request.py index 8f55d00ed4..2dff1c6fac 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -56,14 +56,14 @@ def test_standard_behaviour_determines_no_content_GET(self): Ensure request.data returns empty QueryDict for GET request. """ request = Request(factory.get('/')) - assert request.data == {} + assert request.data is None def test_standard_behaviour_determines_no_content_HEAD(self): """ Ensure request.data returns empty QueryDict for HEAD request. """ request = Request(factory.head('/')) - assert request.data == {} + assert request.data is None def test_request_DATA_with_form_content(self): """ diff --git a/tests/test_testing.py b/tests/test_testing.py index cc60e4f003..99c6a1d7a6 100644 --- a/tests/test_testing.py +++ b/tests/test_testing.py @@ -42,6 +42,7 @@ class BasicSerializer(serializers.Serializer): @api_view(['POST']) def post_view(request): serializer = BasicSerializer(data=request.data) + serializer.allow_null = ('allow_null' in request.query_params) serializer.is_valid(raise_exception=True) return Response(serializer.validated_data) @@ -191,7 +192,26 @@ def test_invalid_multipart_data(self): path='/view/', data={'valid': 123, 'invalid': {'a': 123}} ) - def test_empty_post_uses_default_boolean_value(self): + def test_missing_post_payload_causes_400(self): + response = self.client.post( + '/post-view/', + data=None, + content_type='application/json' + ) + assert response.status_code == 400 + assert response.data['non_field_errors'] == ['No data provided'] + + def test_missing_post_payload_allow_null_causes_200(self): + response = self.client.post( + '/post-view/?allow_null=1', + data=None, + content_type='application/json' + ) + assert response.status_code == 200 + assert response.data is None + + @override_settings(REST_FRAMEWORK={'DEFAULT_MISSING_DATA': {}}) + def test_missing_post_payload_coerced_dict_uses_default_boolean_value(self): response = self.client.post( '/post-view/', data=None, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy