mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-27 16:40:03 +03:00
Merge branch 'master' of https://github.com/encode/django-rest-framework
This commit is contained in:
commit
0b0aff3454
|
@ -103,6 +103,16 @@ Unlike other renderers, the data passed to the `Response` does not need to be se
|
||||||
|
|
||||||
The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context.
|
The TemplateHTMLRenderer will create a `RequestContext`, using the `response.data` as the context dict, and determine a template name to use to render the context.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Note:** When used with a view that makes use of a serializer the `Response` sent for rendering may not be a dictionay and will need to be wrapped in a dict before returning to allow the TemplateHTMLRenderer to render it. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
response.data = {'results': response.data}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
The template name is determined by (in order of preference):
|
The template name is determined by (in order of preference):
|
||||||
|
|
||||||
1. An explicit `template_name` argument passed to the response.
|
1. An explicit `template_name` argument passed to the response.
|
||||||
|
|
|
@ -190,11 +190,6 @@ For support please see the [REST framework discussion group][group], try the `#
|
||||||
|
|
||||||
For priority support please sign up for a [professional or premium sponsorship plan](https://fund.django-rest-framework.org/topics/funding/).
|
For priority support please sign up for a [professional or premium sponsorship plan](https://fund.django-rest-framework.org/topics/funding/).
|
||||||
|
|
||||||
For updates on REST framework development, you may also want to follow [the author][twitter] on Twitter.
|
|
||||||
|
|
||||||
<a style="padding-top: 10px" href="https://twitter.com/_tomchristie" class="twitter-follow-button" data-show-count="false">Follow @_tomchristie</a>
|
|
||||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
If you believe you’ve found something in Django REST framework which has security implications, please **do not raise the issue in a public forum**.
|
If you believe you’ve found something in Django REST framework which has security implications, please **do not raise the issue in a public forum**.
|
||||||
|
|
|
@ -2,3 +2,4 @@
|
||||||
pytest>=5.4.1,<5.5
|
pytest>=5.4.1,<5.5
|
||||||
pytest-django>=3.9.0,<3.10
|
pytest-django>=3.9.0,<3.10
|
||||||
pytest-cov>=2.7.1
|
pytest-cov>=2.7.1
|
||||||
|
six>=1.14.0
|
||||||
|
|
|
@ -20,7 +20,7 @@ def _get_error_details(data, default_code=None):
|
||||||
Descend into a nested data structure, forcing any
|
Descend into a nested data structure, forcing any
|
||||||
lazy translation strings or strings into `ErrorDetail`.
|
lazy translation strings or strings into `ErrorDetail`.
|
||||||
"""
|
"""
|
||||||
if isinstance(data, list):
|
if isinstance(data, (list, tuple)):
|
||||||
ret = [
|
ret = [
|
||||||
_get_error_details(item, default_code) for item in data
|
_get_error_details(item, default_code) for item in data
|
||||||
]
|
]
|
||||||
|
@ -150,7 +150,9 @@ class ValidationError(APIException):
|
||||||
|
|
||||||
# For validation failures, we may collect many errors together,
|
# For validation failures, we may collect many errors together,
|
||||||
# so the details should always be coerced to a list if not already.
|
# so the details should always be coerced to a list if not already.
|
||||||
if not isinstance(detail, dict) and not isinstance(detail, list):
|
if isinstance(detail, tuple):
|
||||||
|
detail = list(detail)
|
||||||
|
elif not isinstance(detail, dict) and not isinstance(detail, list):
|
||||||
detail = [detail]
|
detail = [detail]
|
||||||
|
|
||||||
self.detail = _get_error_details(detail, code)
|
self.detail = _get_error_details(detail, code)
|
||||||
|
|
|
@ -2,6 +2,7 @@ from django.test import TestCase
|
||||||
|
|
||||||
from rest_framework import serializers, status
|
from rest_framework import serializers, status
|
||||||
from rest_framework.decorators import api_view
|
from rest_framework.decorators import api_view
|
||||||
|
from rest_framework.exceptions import ValidationError
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.test import APIRequestFactory
|
from rest_framework.test import APIRequestFactory
|
||||||
|
@ -99,3 +100,12 @@ class TestValidationErrorWithCodes(TestCase):
|
||||||
response = view(request)
|
response = view(request)
|
||||||
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
assert response.status_code == status.HTTP_400_BAD_REQUEST
|
||||||
assert response.data == self.expected_response_data
|
assert response.data == self.expected_response_data
|
||||||
|
|
||||||
|
|
||||||
|
class TestValidationErrorConvertsTuplesToLists(TestCase):
|
||||||
|
def test_validation_error_details(self):
|
||||||
|
error = ValidationError(detail=('message1', 'message2'))
|
||||||
|
assert isinstance(error.detail, list)
|
||||||
|
assert len(error.detail) == 2
|
||||||
|
assert str(error.detail[0]) == 'message1'
|
||||||
|
assert str(error.detail[1]) == 'message2'
|
||||||
|
|
Loading…
Reference in New Issue
Block a user