From 075a0bde5a898825e02b94769513fb66e6af706f Mon Sep 17 00:00:00 2001 From: James Beith Date: Mon, 15 Aug 2016 09:28:46 +0100 Subject: [PATCH 01/14] Fix template syntax error for `as_list_of_strings` (#4403) --- .../templates/rest_framework/vertical/checkbox_multiple.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/templates/rest_framework/vertical/checkbox_multiple.html b/rest_framework/templates/rest_framework/vertical/checkbox_multiple.html index b933f4ff5..7a43b3f58 100644 --- a/rest_framework/templates/rest_framework/vertical/checkbox_multiple.html +++ b/rest_framework/templates/rest_framework/vertical/checkbox_multiple.html @@ -9,7 +9,7 @@
{% for key, text in field.choices.items %} {% endfor %} @@ -18,7 +18,7 @@ {% for key, text in field.choices.items %}
From 785b206b8158eb9c7b05d9d8e94057099fef6fa0 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 15 Aug 2016 16:21:51 +0100 Subject: [PATCH 02/14] Tweak doctsring. Closes #4404 [ci skip] --- rest_framework/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 8f12b2df4..f76e4e801 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -432,7 +432,7 @@ class Field(object): is provided for this field. If a default has not been set for this field then this will simply - return `empty`, indicating that no value should be set in the + raise `SkipField`, indicating that no value should be set in the validated data for this field. """ if self.default is empty or getattr(self.root, 'partial', False): From 101fd29039dc17df3ad317580cf4bcf5ba1c1c03 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 15 Aug 2016 16:53:17 +0100 Subject: [PATCH 03/14] Do not include uploads in request.POST (#4407) --- rest_framework/request.py | 2 +- tests/test_request.py | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index aafafcb32..f5738bfd5 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -373,7 +373,7 @@ class Request(object): if not _hasattr(self, '_data'): self._load_data_and_files() if is_form_media_type(self.content_type): - return self.data + return self._data return QueryDict('', encoding=self._request._encoding) @property diff --git a/tests/test_request.py b/tests/test_request.py index dee636d76..dbfa695fd 100644 --- a/tests/test_request.py +++ b/tests/test_request.py @@ -7,6 +7,7 @@ from django.conf.urls import url from django.contrib.auth import authenticate, login, logout from django.contrib.auth.models import User from django.contrib.sessions.middleware import SessionMiddleware +from django.core.files.uploadedfile import SimpleUploadedFile from django.test import TestCase, override_settings from django.utils import six @@ -78,6 +79,16 @@ class TestContentParsing(TestCase): request.parsers = (FormParser(), MultiPartParser()) self.assertEqual(list(request.POST.items()), list(data.items())) + def test_request_POST_with_files(self): + """ + Ensure request.POST returns no content for POST request with file content. + """ + upload = SimpleUploadedFile("file.txt", b"file_content") + request = Request(factory.post('/', {'upload': upload})) + request.parsers = (FormParser(), MultiPartParser()) + self.assertEqual(list(request.POST.keys()), []) + self.assertEqual(list(request.FILES.keys()), ['upload']) + def test_standard_behaviour_determines_form_content_PUT(self): """ Ensure request.data returns content for PUT request with form content. From e3f8d06bafd37780d6010b0a963029a3448d5e54 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 15 Aug 2016 17:10:55 +0100 Subject: [PATCH 04/14] Include .action attribute on viewsets when generating schemas (#4408) --- rest_framework/schemas.py | 7 +++++++ tests/test_schemas.py | 1 + 2 files changed, 8 insertions(+) diff --git a/rest_framework/schemas.py b/rest_framework/schemas.py index 0618e94fd..c9834c64d 100644 --- a/rest_framework/schemas.py +++ b/rest_framework/schemas.py @@ -79,6 +79,13 @@ class SchemaGenerator(object): view.kwargs = {} view.format_kwarg = None + actions = getattr(callback, 'actions', None) + if actions is not None: + if method == 'OPTIONS': + view.action = 'metadata' + else: + view.action = actions.get(method.lower()) + if request is not None: view.request = clone_request(request, method) try: diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 81b796c35..c866e09be 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -49,6 +49,7 @@ class ExampleViewSet(ModelViewSet): def get_serializer(self, *args, **kwargs): assert self.request + assert self.action return super(ExampleViewSet, self).get_serializer(*args, **kwargs) From 966330a85a404b2967883c5366548cad4e3586d0 Mon Sep 17 00:00:00 2001 From: nevun Date: Wed, 17 Aug 2016 20:42:40 +0200 Subject: [PATCH 05/14] Replace utf8 character ' with its ascii counterpart, makes bdist_rpm.py happy on centos7 (#4412) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 179f2891a..e1e252609 100644 --- a/README.md +++ b/README.md @@ -169,7 +169,7 @@ You may also want to [follow the author on Twitter][twitter]. # 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**. Send a description of the issue via email to [rest-framework-security@googlegroups.com][security-mail]. The project maintainers will then work with you to resolve any issues where required, prior to any public disclosure. From b76984d222281e58e3105df0128141567b9a7697 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 18 Aug 2016 11:24:03 +0100 Subject: [PATCH 06/14] Allow custom CSRF_HEADER_NAME setting. (#4415) --- rest_framework/renderers.py | 9 ++++++++- rest_framework/static/rest_framework/js/csrf.js | 2 +- rest_framework/templates/rest_framework/admin.html | 1 + rest_framework/templates/rest_framework/base.html | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 371cd6ec7..11e9fb960 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -645,6 +645,12 @@ class BrowsableAPIRenderer(BaseRenderer): else: paginator = None + csrf_cookie_name = settings.CSRF_COOKIE_NAME + csrf_header_name = getattr(settings, 'CSRF_HEADER_NAME', 'HTTP_X_CSRFToken') # Fallback for Django 1.8 + if csrf_header_name.startswith('HTTP_'): + csrf_header_name = csrf_header_name[5:] + csrf_header_name = csrf_header_name.replace('_', '-') + context = { 'content': self.get_content(renderer, data, accepted_media_type, renderer_context), 'view': view, @@ -675,7 +681,8 @@ class BrowsableAPIRenderer(BaseRenderer): 'display_edit_forms': bool(response.status_code != 403), 'api_settings': api_settings, - 'csrf_cookie_name': settings.CSRF_COOKIE_NAME, + 'csrf_cookie_name': csrf_cookie_name, + 'csrf_header_name': csrf_header_name } return context diff --git a/rest_framework/static/rest_framework/js/csrf.js b/rest_framework/static/rest_framework/js/csrf.js index f8ab4428c..97c8d0124 100644 --- a/rest_framework/static/rest_framework/js/csrf.js +++ b/rest_framework/static/rest_framework/js/csrf.js @@ -46,7 +46,7 @@ $.ajaxSetup({ // Send the token to same-origin, relative URLs only. // Send the token only if the method warrants CSRF protection // Using the CSRFToken value acquired earlier - xhr.setRequestHeader("X-CSRFToken", csrftoken); + xhr.setRequestHeader(window.drf.csrfHeaderName, csrftoken); } } }); diff --git a/rest_framework/templates/rest_framework/admin.html b/rest_framework/templates/rest_framework/admin.html index 89af81ef7..eb2b8f1c7 100644 --- a/rest_framework/templates/rest_framework/admin.html +++ b/rest_framework/templates/rest_framework/admin.html @@ -232,6 +232,7 @@ {% block script %} diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index 4c1136087..989a086ea 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -263,6 +263,7 @@ {% block script %} From 382ea770b50a2615b4a8b99976d9f6a2a2093c71 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 18 Aug 2016 14:42:15 +0100 Subject: [PATCH 07/14] Improve debug error handling (#4416) --- rest_framework/request.py | 5 +++++ rest_framework/views.py | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/rest_framework/request.py b/rest_framework/request.py index f5738bfd5..355cccad7 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -391,3 +391,8 @@ class Request(object): '`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` ' 'since version 3.0, and has been fully removed as of version 3.2.' ) + + def force_plaintext_errors(self, value): + # Hack to allow our exception handler to force choice of + # plaintext or html error responses. + self._request.is_ajax = lambda: value diff --git a/rest_framework/views.py b/rest_framework/views.py index b86bb7eaa..15d8c6cde 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -3,17 +3,14 @@ Provides an APIView class that is the base of all views in REST framework. """ from __future__ import unicode_literals -import sys - from django.conf import settings from django.core.exceptions import PermissionDenied from django.db import models from django.http import Http404 -from django.http.response import HttpResponse, HttpResponseBase +from django.http.response import HttpResponseBase from django.utils import six from django.utils.encoding import smart_text from django.utils.translation import ugettext_lazy as _ -from django.views import debug from django.views.decorators.csrf import csrf_exempt from django.views.generic import View @@ -95,11 +92,6 @@ def exception_handler(exc, context): set_rollback() return Response(data, status=status.HTTP_403_FORBIDDEN) - # throw django's error page if debug is True - if settings.DEBUG: - exception_reporter = debug.ExceptionReporter(context.get('request'), *sys.exc_info()) - return HttpResponse(exception_reporter.get_traceback_html(), status=500) - return None @@ -439,11 +431,19 @@ class APIView(View): response = exception_handler(exc, context) if response is None: - raise + self.raise_uncaught_exception(exc) response.exception = True return response + def raise_uncaught_exception(self, exc): + if settings.DEBUG: + request = self.request + renderer_format = getattr(request.accepted_renderer, 'format') + use_plaintext_traceback = renderer_format not in ('html', 'api', 'admin') + request.force_plaintext_errors(use_plaintext_traceback) + raise + # Note: Views are made CSRF exempt from within `as_view` as to prevent # accidental removal of this exemption in cases where `dispatch` needs to # be overridden. From 59ca61abcd3083d849843270e491cfa03cd14f79 Mon Sep 17 00:00:00 2001 From: Robert Jensen Date: Fri, 19 Aug 2016 06:44:31 -0400 Subject: [PATCH 08/14] Add django-rest-framework-roles to third party packages in permissions docs (#4417) --- docs/api-guide/permissions.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md index 36719c48f..7cdb59531 100644 --- a/docs/api-guide/permissions.md +++ b/docs/api-guide/permissions.md @@ -261,6 +261,10 @@ The [REST Condition][rest-condition] package is another extension for building c The [DRY Rest Permissions][dry-rest-permissions] package provides the ability to define different permissions for individual default and custom actions. This package is made for apps with permissions that are derived from relationships defined in the app's data model. It also supports permission checks being returned to a client app through the API's serializer. Additionally it supports adding permissions to the default and custom list actions to restrict the data they retrive per user. +## Django Rest Framework Roles + +The [Django Rest Framework Roles][django-rest-framework-roles] package makes it easier to parameterize your API over multiple types of users. + [cite]: https://developer.apple.com/library/mac/#documentation/security/Conceptual/AuthenticationAndAuthorizationGuide/Authorization/Authorization.html [authentication]: authentication.md [throttling]: throttling.md @@ -275,3 +279,4 @@ The [DRY Rest Permissions][dry-rest-permissions] package provides the ability to [composed-permissions]: https://github.com/niwibe/djangorestframework-composed-permissions [rest-condition]: https://github.com/caxap/rest_condition [dry-rest-permissions]: https://github.com/Helioscene/dry-rest-permissions +[django-rest-framework-roles]: https://github.com/computer-lab/django-rest-framework-roles From 63342e81db53260ca4a0defc2b7ed00ed9be3698 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 19 Aug 2016 12:45:20 +0100 Subject: [PATCH 09/14] Version 3.4.5 (#4421) --- docs/topics/release-notes.md | 25 +++++++++++++++++++++++++ rest_framework/__init__.py | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 78a5a8ba9..24728a252 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,18 @@ You can determine your currently installed version using `pip freeze`: ## 3.4.x series +### 3.4.5 + +**Date**: [19th August 2016][3.4.5-milestone] + +* Improve debug error handling. ([#4416][gh4416], [#4409][gh4409]) +* Allow custom CSRF_HEADER_NAME setting. ([#4415][gh4415], [#4410][gh4410]) +* Include .action attribute on viewsets when generating schemas. ([#4408][gh4408], [#4398][gh4398]) +* Do not include request.FILES items in request.POST. ([#4407][gh4407]) +* Fix rendering of checkbox multiple. ([#4403][gh4403]) +* Fix docstring of Field.get_default. ([#4404][gh4404]) +* Replace utf8 character with its ascii counterpart in README. ([#4412][gh4412]) + ### 3.4.4 **Date**: [12th August 2016][3.4.4-milestone] @@ -560,6 +572,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.4.2-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.2+Release%22 [3.4.3-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.3+Release%22 [3.4.4-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.4+Release%22 +[3.4.5-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.5+Release%22 [gh2013]: https://github.com/tomchristie/django-rest-framework/issues/2013 @@ -1065,3 +1078,15 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh4392]: https://github.com/tomchristie/django-rest-framework/issues/4392 [gh4393]: https://github.com/tomchristie/django-rest-framework/issues/4393 [gh4394]: https://github.com/tomchristie/django-rest-framework/issues/4394 + + +[gh4416]: https://github.com/tomchristie/django-rest-framework/issues/4416 +[gh4409]: https://github.com/tomchristie/django-rest-framework/issues/4409 +[gh4415]: https://github.com/tomchristie/django-rest-framework/issues/4415 +[gh4410]: https://github.com/tomchristie/django-rest-framework/issues/4410 +[gh4408]: https://github.com/tomchristie/django-rest-framework/issues/4408 +[gh4398]: https://github.com/tomchristie/django-rest-framework/issues/4398 +[gh4407]: https://github.com/tomchristie/django-rest-framework/issues/4407 +[gh4403]: https://github.com/tomchristie/django-rest-framework/issues/4403 +[gh4404]: https://github.com/tomchristie/django-rest-framework/issues/4404 +[gh4412]: https://github.com/tomchristie/django-rest-framework/issues/4412 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 999c5de31..3f8736c25 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.4.4' +__version__ = '3.4.5' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2016 Tom Christie' From a335309b33e5e99a968d36a0a778e0872adab3a8 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Fri, 19 Aug 2016 14:37:27 +0100 Subject: [PATCH 10/14] Add __str__ method to PKOnlyObject (#4423) --- rest_framework/relations.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 4b6b3bea4..65c4c0318 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -10,7 +10,7 @@ from django.core.urlresolvers import ( from django.db.models import Manager from django.db.models.query import QuerySet from django.utils import six -from django.utils.encoding import smart_text +from django.utils.encoding import python_2_unicode_compatible, smart_text from django.utils.six.moves.urllib import parse as urlparse from django.utils.translation import ugettext_lazy as _ @@ -47,6 +47,7 @@ class Hyperlink(six.text_type): is_hyperlink = True +@python_2_unicode_compatible class PKOnlyObject(object): """ This is a mock object, used for when we only need the pk of the object @@ -56,6 +57,9 @@ class PKOnlyObject(object): def __init__(self, pk): self.pk = pk + def __str__(self): + return "%s" % self.pk + # We assume that 'validators' are intended for the child serializer, # rather than the parent serializer. From d540f0262b4b0a5f8ce628334d1a812179556002 Mon Sep 17 00:00:00 2001 From: orf Date: Fri, 19 Aug 2016 14:42:13 +0100 Subject: [PATCH 11/14] Improve Create to show the original exception traceback (#3508) --- rest_framework/serializers.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 41412af8a..4d1ed63ae 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -12,6 +12,7 @@ response content is handled by parsers and renderers. """ from __future__ import unicode_literals +import traceback import warnings from django.db import models @@ -870,19 +871,20 @@ class ModelSerializer(Serializer): try: instance = ModelClass.objects.create(**validated_data) - except TypeError as exc: + except TypeError: + tb = traceback.format_exc() msg = ( 'Got a `TypeError` when calling `%s.objects.create()`. ' 'This may be because you have a writable field on the ' 'serializer class that is not a valid argument to ' '`%s.objects.create()`. You may need to make the field ' 'read-only, or override the %s.create() method to handle ' - 'this correctly.\nOriginal exception text was: %s.' % + 'this correctly.\nOriginal exception was:\n %s' % ( ModelClass.__name__, ModelClass.__name__, self.__class__.__name__, - exc + tb ) ) raise TypeError(msg) From d0ed482d7094e94b8cbfdc6c0f8335e02d79b765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Mon, 22 Aug 2016 11:53:53 -0400 Subject: [PATCH 12/14] Skip HiddenField from Schema fields (#4429) --- rest_framework/schemas.py | 3 ++- tests/test_schemas.py | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/rest_framework/schemas.py b/rest_framework/schemas.py index c9834c64d..1b899450f 100644 --- a/rest_framework/schemas.py +++ b/rest_framework/schemas.py @@ -296,8 +296,9 @@ class SchemaGenerator(object): fields = [] for field in serializer.fields.values(): - if field.read_only: + if field.read_only or isinstance(field, serializers.HiddenField): continue + required = field.required and method != 'PATCH' description = force_text(field.help_text) if field.help_text else '' field = coreapi.Field( diff --git a/tests/test_schemas.py b/tests/test_schemas.py index c866e09be..197e62eb0 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -26,6 +26,8 @@ class ExamplePagination(pagination.PageNumberPagination): class ExampleSerializer(serializers.Serializer): a = serializers.CharField(required=True, help_text='A field description') b = serializers.CharField(required=False) + read_only = serializers.CharField(read_only=True) + hidden = serializers.HiddenField(default='hello') class AnotherSerializer(serializers.Serializer): From 97806f9724fc315518c881a439a5aa82a46c0e34 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 23 Aug 2016 09:46:03 +0100 Subject: [PATCH 13/14] Add missing comma --- rest_framework/templates/rest_framework/base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index 989a086ea..7f5170a62 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -263,7 +263,7 @@ {% block script %} From f064ec6ac612e5a24d8a7cd21c06c4b8243e549c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 23 Aug 2016 16:59:47 +0100 Subject: [PATCH 14/14] Version 3.4.6 (#4436) --- docs/topics/release-notes.md | 19 +++++++++++++++++++ rest_framework/__init__.py | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 24728a252..63aa4e4a3 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,15 @@ You can determine your currently installed version using `pip freeze`: ## 3.4.x series +### 3.4.6 + +**Date**: [23rd August 2016][3.4.6-milestone] + +* Fix malformed Javascript in browsable API. ([#4435][gh4435]) +* Skip HiddenField from Schema fields. ([#4425][gh4425], [#4429][gh4429]) +* Improve Create to show the original exception traceback. ([#3508][gh3508]) +* Fix `AdminRenderer` display of PK only related fields. ([#4419][gh4419], [#4423][gh4423]) + ### 3.4.5 **Date**: [19th August 2016][3.4.5-milestone] @@ -573,6 +582,7 @@ For older release notes, [please see the version 2.x documentation][old-release- [3.4.3-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.3+Release%22 [3.4.4-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.4+Release%22 [3.4.5-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.5+Release%22 +[3.4.6-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.4.6+Release%22 [gh2013]: https://github.com/tomchristie/django-rest-framework/issues/2013 @@ -1090,3 +1100,12 @@ For older release notes, [please see the version 2.x documentation][old-release- [gh4403]: https://github.com/tomchristie/django-rest-framework/issues/4403 [gh4404]: https://github.com/tomchristie/django-rest-framework/issues/4404 [gh4412]: https://github.com/tomchristie/django-rest-framework/issues/4412 + + + +[gh4435]: https://github.com/tomchristie/django-rest-framework/issues/4435 +[gh4425]: https://github.com/tomchristie/django-rest-framework/issues/4425 +[gh4429]: https://github.com/tomchristie/django-rest-framework/issues/4429 +[gh3508]: https://github.com/tomchristie/django-rest-framework/issues/3508 +[gh4419]: https://github.com/tomchristie/django-rest-framework/issues/4419 +[gh4423]: https://github.com/tomchristie/django-rest-framework/issues/4423 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index 3f8736c25..d99d82d23 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.4.5' +__version__ = '3.4.6' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2016 Tom Christie'