From 60c17253ab5618e071bc51b0ce9df8053bda9ae3 Mon Sep 17 00:00:00 2001 From: Cesar Canassa Date: Mon, 3 Aug 2015 17:54:18 +0200 Subject: [PATCH 1/7] Add test to check if a 415 status is returned for unsupported media types --- tests/test_response.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/test_response.py b/tests/test_response.py index 1dd5d5ea0..b53688e5c 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -5,6 +5,7 @@ from django.test import TestCase from django.utils import six from rest_framework import generics, routers, serializers, status, viewsets +from rest_framework.parsers import JSONParser from rest_framework.renderers import ( BaseRenderer, BrowsableAPIRenderer, JSONRenderer ) @@ -79,6 +80,14 @@ class MockViewSettingContentType(APIView): return Response(DUMMYCONTENT, status=DUMMYSTATUS, content_type='setbyview') +class JSONView(APIView): + parser_classes = (JSONParser,) + + def post(self, request, **kwargs): + assert request.data + return Response(DUMMYCONTENT) + + class HTMLView(APIView): renderer_classes = (BrowsableAPIRenderer, ) @@ -114,6 +123,7 @@ urlpatterns = [ url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])), url(r'^html$', HTMLView.as_view()), + url(r'^json$', JSONView.as_view()), url(r'^html1$', HTMLView1.as_view()), url(r'^html_new_model$', HTMLNewModelView.as_view()), url(r'^html_new_model_viewset', include(new_model_viewset_router.urls)), @@ -203,6 +213,25 @@ class RendererIntegrationTests(TestCase): self.assertEqual(resp.status_code, DUMMYSTATUS) +class UnsupportedMediaTypeTests(TestCase): + urls = 'tests.test_response' + + def test_should_allow_posting_json(self): + response = self.client.post('/json', data='{"test": 123}', content_type='application/json') + + self.assertEqual(response.status_code, 200) + + def test_should_not_allow_posting_xml(self): + response = self.client.post('/json', data='123', content_type='application/xml') + + self.assertEqual(response.status_code, 415) + + def test_should_not_allow_posting_a_form(self): + response = self.client.post('/json', data={'test': 123}) + + self.assertEqual(response.status_code, 415) + + class Issue122Tests(TestCase): """ Tests that covers #122. From 1a8f9d0a0f7edb7a138bd37e31772ff56dbceb2c Mon Sep 17 00:00:00 2001 From: qqbuby Date: Sat, 12 Sep 2015 01:36:40 +0800 Subject: [PATCH 2/7] fix issue #3395 to correct the output text at line 184in docs/tutorial/1-serialization.md --- docs/tutorial/1-serialization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index c54af0cec..e26db8be3 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -181,7 +181,7 @@ We can also serialize querysets instead of model instances. To do so we simply serializer = SnippetSerializer(Snippet.objects.all(), many=True) serializer.data - # [{'pk': 1, 'title': u'', 'code': u'foo = "bar"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}, {'pk': 2, 'title': u'', 'code': u'print "hello, world"\n', 'linenos': False, 'language': u'python', 'style': u'friendly'}] + #[OrderedDict([('pk', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])] ## Using ModelSerializers From 284f9faa07941a2c804909187211cc782e7c96c9 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Fri, 11 Sep 2015 23:01:18 -0400 Subject: [PATCH 3/7] Correctly handle [] and {} as invalid inputs to BooleanField --- rest_framework/fields.py | 11 +++++++---- tests/test_fields.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 159784ea3..7c48c621e 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -608,10 +608,13 @@ class BooleanField(Field): super(BooleanField, self).__init__(**kwargs) def to_internal_value(self, data): - if data in self.TRUE_VALUES: - return True - elif data in self.FALSE_VALUES: - return False + try: + if data in self.TRUE_VALUES: + return True + elif data in self.FALSE_VALUES: + return False + except TypeError: # Input is an unhashable type + pass self.fail('invalid', input=data) def to_representation(self, value): diff --git a/tests/test_fields.py b/tests/test_fields.py index c1d3e3a49..6048f49d0 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -466,6 +466,18 @@ class TestBooleanField(FieldValues): } field = serializers.BooleanField() + def test_disallow_unhashable_collection_types(self): + inputs = ( + [], + {}, + ) + field = serializers.BooleanField() + for input_value in inputs: + with pytest.raises(serializers.ValidationError) as exc_info: + field.run_validation(input_value) + expected = ['"{0}" is not a valid boolean.'.format(input_value)] + assert exc_info.value.detail == expected + class TestNullBooleanField(FieldValues): """ From 5c076e10bbd3defbda05403a678f7397ac5e6f26 Mon Sep 17 00:00:00 2001 From: Nic Young Date: Sat, 12 Sep 2015 23:04:18 -0700 Subject: [PATCH 4/7] Add link to serpy serialization, fixes #3391 --- docs/api-guide/serializers.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/api-guide/serializers.md b/docs/api-guide/serializers.md index 70739689d..ca540a13b 100644 --- a/docs/api-guide/serializers.md +++ b/docs/api-guide/serializers.md @@ -1032,6 +1032,9 @@ The following third party packages are also available. The [django-rest-marshmallow][django-rest-marshmallow] package provides an alternative implementation for serializers, using the python [marshmallow][marshmallow] library. It exposes the same API as the REST framework serializers, and can be used as a drop-in replacement in some use-cases. +## Serpy +The [serpy][serpy] package is an alternative implementation for serializers that is built for speed. [Serpy][serpy] serializes complex datatypes to simple native types. The native types can be easily converted to JSON or any other format needed. + ## MongoengineModelSerializer The [django-rest-framework-mongoengine][mongoengine] package provides a `MongoEngineModelSerializer` serializer class that supports using MongoDB as the storage layer for Django REST framework. @@ -1050,6 +1053,7 @@ The [django-rest-framework-hstore][django-rest-framework-hstore] package provide [encapsulation-blogpost]: http://www.dabapps.com/blog/django-models-and-encapsulation/ [django-rest-marshmallow]: http://tomchristie.github.io/django-rest-marshmallow/ [marshmallow]: https://marshmallow.readthedocs.org/en/latest/ +[serpy]: https://github.com/clarkduvall/serpy [mongoengine]: https://github.com/umutbozkurt/django-rest-framework-mongoengine [django-rest-framework-gis]: https://github.com/djangonauts/django-rest-framework-gis [django-rest-framework-hstore]: https://github.com/djangonauts/django-rest-framework-hstore From 1aa16caffe6a6e7eba409cc1a4be2f9a05777cd6 Mon Sep 17 00:00:00 2001 From: qqbuby Date: Sun, 13 Sep 2015 20:24:22 +0800 Subject: [PATCH 5/7] append a space after the comment mark to remain consistent with the other parts of the tutorial --- docs/tutorial/1-serialization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index e26db8be3..890f8d561 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -181,7 +181,7 @@ We can also serialize querysets instead of model instances. To do so we simply serializer = SnippetSerializer(Snippet.objects.all(), many=True) serializer.data - #[OrderedDict([('pk', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])] + # [OrderedDict([('pk', 1), ('title', u''), ('code', u'foo = "bar"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 2), ('title', u''), ('code', u'print "hello, world"\n'), ('linenos', False), ('language', 'python'), ('style', 'friendly')]), OrderedDict([('pk', 3), ('title', u''), ('code', u'print "hello, world"'), ('linenos', False), ('language', 'python'), ('style', 'friendly')])] ## Using ModelSerializers From 6baca948309da5cc67f25cdfda8eb7198700541f Mon Sep 17 00:00:00 2001 From: James McMahon Date: Mon, 14 Sep 2015 19:34:07 +0100 Subject: [PATCH 6/7] added knox package reference to 3rd party auth apps --- docs/api-guide/authentication.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index 2ccf7d721..7fda98e67 100644 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -360,6 +360,10 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [Django-rest-auth][django-rest-auth] library provides a set of REST API endpoints for registration, authentication (including social media authentication), password reset, retrieve and update user details, etc. By having these API endpoints, your client apps such as AngularJS, iOS, Android, and others can communicate to your Django backend site independently via REST APIs for user management. +## django-rest-knox + +[Django-rest-knox][django-rest-knox] library provides models and views to handle token based authentication in a more secure and extensible way than the built-in TokenAuthentication scheme - with Single Page Applications and Mobile clients in mind. It provides per-client tokens, and views to generate them when provided some other authentication (usually basic authentication), to delete the token (providing a server enforced logout) and to delete all tokens (logs out all clients that a user is logged into). + [cite]: http://jacobian.org/writing/rest-worst-practices/ [http401]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.2 [http403]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4 @@ -400,3 +404,4 @@ HTTP Signature (currently a [IETF draft][http-signature-ietf-draft]) provides a [mac]: http://tools.ietf.org/html/draft-hammer-oauth-v2-mac-token-05 [djoser]: https://github.com/sunscrapers/djoser [django-rest-auth]: https://github.com/Tivix/django-rest-auth +[django-rest-knox]: https://github.com/James1345/django-rest-knox From 4e7d0493db7ca415980752f37e5ccc837503be8d Mon Sep 17 00:00:00 2001 From: Nic Young Date: Mon, 14 Sep 2015 21:05:28 -0700 Subject: [PATCH 7/7] Update transifex-client requirement to latest release version --- requirements/requirements-packaging.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/requirements-packaging.txt b/requirements/requirements-packaging.txt index 1efb2f836..7510dbd79 100644 --- a/requirements/requirements-packaging.txt +++ b/requirements/requirements-packaging.txt @@ -5,4 +5,4 @@ wheel==0.24.0 twine==1.4.0 # Transifex client for managing translation resources. -transifex-client==0.10 +transifex-client==0.11b3