Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/api-guide/requests.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,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].

Expand Down
7 changes: 7 additions & 0 deletions docs/api-guide/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,13 @@ A view inspector class that will be used for schema generation.

Default: `'rest_framework.schemas.openapi.AutoSchema'`

#### DEFAULT_MISSING_DATA
Comment thread
peterthomassen marked this conversation as resolved.

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
Expand Down
2 changes: 1 addition & 1 deletion rest_framework/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,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
Comment thread
peterthomassen marked this conversation as resolved.
empty_files = MultiValueDict()
return (empty_data, empty_files)

Expand Down
1 change: 1 addition & 0 deletions rest_framework/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,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,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,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):
"""
Expand Down
22 changes: 21 additions & 1 deletion tests/test_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def delete_json_view(request):
@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)

Expand Down Expand Up @@ -244,7 +245,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):
Comment thread
peterthomassen marked this conversation as resolved.
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,
Expand Down