mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
Merge branch 'version-3.2' into remove-url-from-future
This commit is contained in:
commit
ed3f9593af
|
@ -195,7 +195,8 @@ class PageNumberPagination(BasePagination):
|
||||||
"""
|
"""
|
||||||
Prior to version 3.1, pagination was handled in the view, and the
|
Prior to version 3.1, pagination was handled in the view, and the
|
||||||
attributes were set there. The attributes should now be set on
|
attributes were set there. The attributes should now be set on
|
||||||
the pagination class, but the old style is still pending deprecation.
|
the pagination class. The old style continues to work but is deprecated
|
||||||
|
and will be fully removed in version 3.3.
|
||||||
"""
|
"""
|
||||||
assert not (
|
assert not (
|
||||||
getattr(view, 'pagination_serializer_class', None) or
|
getattr(view, 'pagination_serializer_class', None) or
|
||||||
|
@ -216,11 +217,11 @@ class PageNumberPagination(BasePagination):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
setattr(self, attr_name, value)
|
setattr(self, attr_name, value)
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"The `%s` settings key is pending deprecation. "
|
"The `%s` settings key is deprecated. "
|
||||||
"Use the `%s` attribute on the pagination class instead." % (
|
"Use the `%s` attribute on the pagination class instead." % (
|
||||||
settings_key, attr_name
|
settings_key, attr_name
|
||||||
),
|
),
|
||||||
PendingDeprecationWarning,
|
DeprecationWarning,
|
||||||
)
|
)
|
||||||
|
|
||||||
for (view_attr, attr_name) in (
|
for (view_attr, attr_name) in (
|
||||||
|
@ -233,11 +234,11 @@ class PageNumberPagination(BasePagination):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
setattr(self, attr_name, value)
|
setattr(self, attr_name, value)
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
"The `%s` view attribute is pending deprecation. "
|
"The `%s` view attribute is deprecated. "
|
||||||
"Use the `%s` attribute on the pagination class instead." % (
|
"Use the `%s` attribute on the pagination class instead." % (
|
||||||
view_attr, attr_name
|
view_attr, attr_name
|
||||||
),
|
),
|
||||||
PendingDeprecationWarning,
|
DeprecationWarning,
|
||||||
)
|
)
|
||||||
|
|
||||||
def paginate_queryset(self, queryset, request, view=None):
|
def paginate_queryset(self, queryset, request, view=None):
|
||||||
|
|
|
@ -203,58 +203,12 @@ class Request(object):
|
||||||
"""
|
"""
|
||||||
return self._request.GET
|
return self._request.GET
|
||||||
|
|
||||||
@property
|
|
||||||
def QUERY_PARAMS(self):
|
|
||||||
"""
|
|
||||||
Synonym for `.query_params`, for backwards compatibility.
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"`request.QUERY_PARAMS` is deprecated. Use `request.query_params` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=1
|
|
||||||
)
|
|
||||||
return self._request.GET
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def data(self):
|
def data(self):
|
||||||
if not _hasattr(self, '_full_data'):
|
if not _hasattr(self, '_full_data'):
|
||||||
self._load_data_and_files()
|
self._load_data_and_files()
|
||||||
return self._full_data
|
return self._full_data
|
||||||
|
|
||||||
@property
|
|
||||||
def DATA(self):
|
|
||||||
"""
|
|
||||||
Parses the request body and returns the data.
|
|
||||||
|
|
||||||
Similar to usual behaviour of `request.POST`, except that it handles
|
|
||||||
arbitrary parsers, and also works on methods other than POST (eg PUT).
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"`request.DATA` is deprecated. Use `request.data` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=1
|
|
||||||
)
|
|
||||||
if not _hasattr(self, '_data'):
|
|
||||||
self._load_data_and_files()
|
|
||||||
return self._data
|
|
||||||
|
|
||||||
@property
|
|
||||||
def FILES(self):
|
|
||||||
"""
|
|
||||||
Parses the request body and returns any files uploaded in the request.
|
|
||||||
|
|
||||||
Similar to usual behaviour of `request.FILES`, except that it handles
|
|
||||||
arbitrary parsers, and also works on methods other than POST (eg PUT).
|
|
||||||
"""
|
|
||||||
warnings.warn(
|
|
||||||
"`request.FILES` is deprecated. Use `request.data` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=1
|
|
||||||
)
|
|
||||||
if not _hasattr(self, '_files'):
|
|
||||||
self._load_data_and_files()
|
|
||||||
return self._files
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def user(self):
|
def user(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1179,44 +1179,6 @@ class ModelSerializer(Serializer):
|
||||||
kwargs['read_only'] = True
|
kwargs['read_only'] = True
|
||||||
extra_kwargs[field_name] = kwargs
|
extra_kwargs[field_name] = kwargs
|
||||||
|
|
||||||
# These are all pending deprecation.
|
|
||||||
write_only_fields = getattr(self.Meta, 'write_only_fields', None)
|
|
||||||
if write_only_fields is not None:
|
|
||||||
warnings.warn(
|
|
||||||
"The `Meta.write_only_fields` option is deprecated. "
|
|
||||||
"Use `Meta.extra_kwargs={<field_name>: {'write_only': True}}` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3
|
|
||||||
)
|
|
||||||
for field_name in write_only_fields:
|
|
||||||
kwargs = extra_kwargs.get(field_name, {})
|
|
||||||
kwargs['write_only'] = True
|
|
||||||
extra_kwargs[field_name] = kwargs
|
|
||||||
|
|
||||||
view_name = getattr(self.Meta, 'view_name', None)
|
|
||||||
if view_name is not None:
|
|
||||||
warnings.warn(
|
|
||||||
"The `Meta.view_name` option is deprecated. "
|
|
||||||
"Use `Meta.extra_kwargs={'url': {'view_name': ...}}` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3
|
|
||||||
)
|
|
||||||
kwargs = extra_kwargs.get(self.url_field_name, {})
|
|
||||||
kwargs['view_name'] = view_name
|
|
||||||
extra_kwargs[self.url_field_name] = kwargs
|
|
||||||
|
|
||||||
lookup_field = getattr(self.Meta, 'lookup_field', None)
|
|
||||||
if lookup_field is not None:
|
|
||||||
warnings.warn(
|
|
||||||
"The `Meta.lookup_field` option is deprecated. "
|
|
||||||
"Use `Meta.extra_kwargs={'url': {'lookup_field': ...}}` instead.",
|
|
||||||
DeprecationWarning,
|
|
||||||
stacklevel=3
|
|
||||||
)
|
|
||||||
kwargs = extra_kwargs.get(self.url_field_name, {})
|
|
||||||
kwargs['lookup_field'] = lookup_field
|
|
||||||
extra_kwargs[self.url_field_name] = kwargs
|
|
||||||
|
|
||||||
return extra_kwargs
|
return extra_kwargs
|
||||||
|
|
||||||
def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs):
|
def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs):
|
||||||
|
|
|
@ -425,14 +425,6 @@ class APIView(View):
|
||||||
|
|
||||||
exception_handler = self.settings.EXCEPTION_HANDLER
|
exception_handler = self.settings.EXCEPTION_HANDLER
|
||||||
|
|
||||||
if len(inspect.getargspec(exception_handler).args) == 1:
|
|
||||||
warnings.warn(
|
|
||||||
'The `exception_handler(exc)` call signature is deprecated. '
|
|
||||||
'Use `exception_handler(exc, context) instead.',
|
|
||||||
DeprecationWarning
|
|
||||||
)
|
|
||||||
response = exception_handler(exc)
|
|
||||||
else:
|
|
||||||
context = self.get_exception_handler_context()
|
context = self.get_exception_handler_context()
|
||||||
response = exception_handler(exc, context)
|
response = exception_handler(exc, context)
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@ class MockGETView(APIView):
|
||||||
|
|
||||||
class MockPOSTView(APIView):
|
class MockPOSTView(APIView):
|
||||||
def post(self, request, **kwargs):
|
def post(self, request, **kwargs):
|
||||||
return Response({'foo': request.DATA})
|
return Response({'foo': request.data})
|
||||||
|
|
||||||
|
|
||||||
class EmptyGETView(APIView):
|
class EmptyGETView(APIView):
|
||||||
|
|
|
@ -76,37 +76,37 @@ class TestMethodOverloading(TestCase):
|
||||||
class TestContentParsing(TestCase):
|
class TestContentParsing(TestCase):
|
||||||
def test_standard_behaviour_determines_no_content_GET(self):
|
def test_standard_behaviour_determines_no_content_GET(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns empty QueryDict for GET request.
|
Ensure request.data returns empty QueryDict for GET request.
|
||||||
"""
|
"""
|
||||||
request = Request(factory.get('/'))
|
request = Request(factory.get('/'))
|
||||||
self.assertEqual(request.DATA, {})
|
self.assertEqual(request.data, {})
|
||||||
|
|
||||||
def test_standard_behaviour_determines_no_content_HEAD(self):
|
def test_standard_behaviour_determines_no_content_HEAD(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns empty QueryDict for HEAD request.
|
Ensure request.data returns empty QueryDict for HEAD request.
|
||||||
"""
|
"""
|
||||||
request = Request(factory.head('/'))
|
request = Request(factory.head('/'))
|
||||||
self.assertEqual(request.DATA, {})
|
self.assertEqual(request.data, {})
|
||||||
|
|
||||||
def test_request_DATA_with_form_content(self):
|
def test_request_DATA_with_form_content(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for POST request with form content.
|
Ensure request.data returns content for POST request with form content.
|
||||||
"""
|
"""
|
||||||
data = {'qwerty': 'uiop'}
|
data = {'qwerty': 'uiop'}
|
||||||
request = Request(factory.post('/', data))
|
request = Request(factory.post('/', data))
|
||||||
request.parsers = (FormParser(), MultiPartParser())
|
request.parsers = (FormParser(), MultiPartParser())
|
||||||
self.assertEqual(list(request.DATA.items()), list(data.items()))
|
self.assertEqual(list(request.data.items()), list(data.items()))
|
||||||
|
|
||||||
def test_request_DATA_with_text_content(self):
|
def test_request_DATA_with_text_content(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for POST request with
|
Ensure request.data returns content for POST request with
|
||||||
non-form content.
|
non-form content.
|
||||||
"""
|
"""
|
||||||
content = six.b('qwerty')
|
content = six.b('qwerty')
|
||||||
content_type = 'text/plain'
|
content_type = 'text/plain'
|
||||||
request = Request(factory.post('/', content, content_type=content_type))
|
request = Request(factory.post('/', content, content_type=content_type))
|
||||||
request.parsers = (PlainTextParser(),)
|
request.parsers = (PlainTextParser(),)
|
||||||
self.assertEqual(request.DATA, content)
|
self.assertEqual(request.data, content)
|
||||||
|
|
||||||
def test_request_POST_with_form_content(self):
|
def test_request_POST_with_form_content(self):
|
||||||
"""
|
"""
|
||||||
|
@ -119,27 +119,27 @@ class TestContentParsing(TestCase):
|
||||||
|
|
||||||
def test_standard_behaviour_determines_form_content_PUT(self):
|
def test_standard_behaviour_determines_form_content_PUT(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for PUT request with form content.
|
Ensure request.data returns content for PUT request with form content.
|
||||||
"""
|
"""
|
||||||
data = {'qwerty': 'uiop'}
|
data = {'qwerty': 'uiop'}
|
||||||
request = Request(factory.put('/', data))
|
request = Request(factory.put('/', data))
|
||||||
request.parsers = (FormParser(), MultiPartParser())
|
request.parsers = (FormParser(), MultiPartParser())
|
||||||
self.assertEqual(list(request.DATA.items()), list(data.items()))
|
self.assertEqual(list(request.data.items()), list(data.items()))
|
||||||
|
|
||||||
def test_standard_behaviour_determines_non_form_content_PUT(self):
|
def test_standard_behaviour_determines_non_form_content_PUT(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for PUT request with
|
Ensure request.data returns content for PUT request with
|
||||||
non-form content.
|
non-form content.
|
||||||
"""
|
"""
|
||||||
content = six.b('qwerty')
|
content = six.b('qwerty')
|
||||||
content_type = 'text/plain'
|
content_type = 'text/plain'
|
||||||
request = Request(factory.put('/', content, content_type=content_type))
|
request = Request(factory.put('/', content, content_type=content_type))
|
||||||
request.parsers = (PlainTextParser(), )
|
request.parsers = (PlainTextParser(), )
|
||||||
self.assertEqual(request.DATA, content)
|
self.assertEqual(request.data, content)
|
||||||
|
|
||||||
def test_overloaded_behaviour_allows_content_tunnelling(self):
|
def test_overloaded_behaviour_allows_content_tunnelling(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for overloaded POST request.
|
Ensure request.data returns content for overloaded POST request.
|
||||||
"""
|
"""
|
||||||
json_data = {'foobar': 'qwerty'}
|
json_data = {'foobar': 'qwerty'}
|
||||||
content = json.dumps(json_data)
|
content = json.dumps(json_data)
|
||||||
|
@ -150,7 +150,7 @@ class TestContentParsing(TestCase):
|
||||||
}
|
}
|
||||||
request = Request(factory.post('/', form_data))
|
request = Request(factory.post('/', form_data))
|
||||||
request.parsers = (JSONParser(), )
|
request.parsers = (JSONParser(), )
|
||||||
self.assertEqual(request.DATA, json_data)
|
self.assertEqual(request.data, json_data)
|
||||||
|
|
||||||
def test_form_POST_unicode(self):
|
def test_form_POST_unicode(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -25,7 +25,7 @@ class BasicView(APIView):
|
||||||
return Response({'method': 'GET'})
|
return Response({'method': 'GET'})
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
return Response({'method': 'POST', 'data': request.DATA})
|
return Response({'method': 'POST', 'data': request.data})
|
||||||
|
|
||||||
|
|
||||||
@api_view(['GET', 'POST', 'PUT', 'PATCH'])
|
@api_view(['GET', 'POST', 'PUT', 'PATCH'])
|
||||||
|
@ -33,11 +33,11 @@ def basic_view(request):
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return {'method': 'GET'}
|
return {'method': 'GET'}
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
return {'method': 'POST', 'data': request.DATA}
|
return {'method': 'POST', 'data': request.data}
|
||||||
elif request.method == 'PUT':
|
elif request.method == 'PUT':
|
||||||
return {'method': 'PUT', 'data': request.DATA}
|
return {'method': 'PUT', 'data': request.data}
|
||||||
elif request.method == 'PATCH':
|
elif request.method == 'PATCH':
|
||||||
return {'method': 'PATCH', 'data': request.DATA}
|
return {'method': 'PATCH', 'data': request.data}
|
||||||
|
|
||||||
|
|
||||||
class ErrorView(APIView):
|
class ErrorView(APIView):
|
||||||
|
@ -123,7 +123,7 @@ class TestCustomExceptionHandler(TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.DEFAULT_HANDLER = api_settings.EXCEPTION_HANDLER
|
self.DEFAULT_HANDLER = api_settings.EXCEPTION_HANDLER
|
||||||
|
|
||||||
def exception_handler(exc):
|
def exception_handler(exc, request):
|
||||||
return Response('Error!', status=status.HTTP_400_BAD_REQUEST)
|
return Response('Error!', status=status.HTTP_400_BAD_REQUEST)
|
||||||
|
|
||||||
api_settings.EXCEPTION_HANDLER = exception_handler
|
api_settings.EXCEPTION_HANDLER = exception_handler
|
||||||
|
|
Loading…
Reference in New Issue
Block a user