From 26ac2656e5e0b3d01a67551910113a305d2a2820 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 5 Jan 2015 16:20:15 +0000 Subject: [PATCH 01/35] Pass init arguments through to serializer from pagination serializer. Closes #2355. Normally a serializer won't need these arguments on __init__, but if a user has customized __init__ they may expect them to be available. --- rest_framework/pagination.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py index f31e5fa4c..9c8dda8f9 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -37,16 +37,13 @@ class PreviousPageField(serializers.Field): return replace_query_param(url, self.page_field, page) -class DefaultObjectSerializer(serializers.ReadOnlyField): +class DefaultObjectSerializer(serializers.Serializer): """ If no object serializer is specified, then this serializer will be applied as the default. """ - - def __init__(self, source=None, many=None, context=None): - # Note: Swallow context and many kwargs - only required for - # eg. ModelSerializer. - super(DefaultObjectSerializer, self).__init__(source=source) + def to_representation(self, value): + return value class BasePaginationSerializer(serializers.Serializer): @@ -74,10 +71,9 @@ class BasePaginationSerializer(serializers.Serializer): list_serializer_class = serializers.ListSerializer self.fields[results_field] = list_serializer_class( - child=object_serializer(), + child=object_serializer(*args, **kwargs), source='object_list' ) - self.fields[results_field].bind(field_name=results_field, parent=self) class PaginationSerializer(BasePaginationSerializer): From d3b2302588f333b22d5e4aa2be6eca0e944e9494 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 5 Jan 2015 16:31:52 +0000 Subject: [PATCH 02/35] Minor docs update. Refs #2375. --- docs/topics/3.0-announcement.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/topics/3.0-announcement.md b/docs/topics/3.0-announcement.md index 68d247827..5dbc5600a 100644 --- a/docs/topics/3.0-announcement.md +++ b/docs/topics/3.0-announcement.md @@ -87,12 +87,12 @@ The resulting API changes are further detailed below. #### The `.create()` and `.update()` methods. -The `.restore_object()` method is now replaced with two separate methods, `.create()` and `.update()`. - -These methods also replace the optional `.save_object()` method, which no longer exists. +The `.restore_object()` method is now removed, and we instead have two separate methods, `.create()` and `.update()`. These methods work slightly different to the previous `.restore_object()`. When using the `.create()` and `.update()` methods you should both create *and save* the object instance. This is in contrast to the previous `.restore_object()` behavior that would instantiate the object but not save it. +These methods also replace the optional `.save_object()` method, which no longer exists. + The following example from the tutorial previously used `restore_object()` to handle both creating and updating object instances. def restore_object(self, attrs, instance=None): From 271b638df10c0cf498cbc69847f388e978c4da78 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Tue, 6 Jan 2015 11:21:58 +0000 Subject: [PATCH 03/35] Update exception docs. Closes #2378. --- docs/api-guide/exceptions.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/api-guide/exceptions.md b/docs/api-guide/exceptions.md index 467ad9709..993134f7f 100644 --- a/docs/api-guide/exceptions.md +++ b/docs/api-guide/exceptions.md @@ -18,7 +18,7 @@ The handled exceptions are: In each case, REST framework will return a response with an appropriate status code and content-type. The body of the response will include any additional details regarding the nature of the error. -By default all error responses will include a key `detail` in the body of the response, but other keys may also be included. +Most error responses will include a key `detail` in the body of the response. For example, the following request: @@ -33,6 +33,16 @@ Might receive an error response indicating that the `DELETE` method is not allow {"detail": "Method 'DELETE' not allowed."} +Validation errors are handled slightly differently, and will include the field names as the keys in the response. If the validation error was not specific to a particular field then it will use the "non_field_errors" key, or whatever string value has been set for the `NON_FIELD_ERRORS_KEY` setting. + +Any example validation error might look like this: + + HTTP/1.1 400 Bad Request + Content-Type: application/json + Content-Length: 94 + + {"amount": ["A valid integer is required."], "description": ["This field may not be blank."]} + ## Custom exception handling You can implement custom exception handling by creating a handler function that converts exceptions raised in your API views into response objects. This allows you to control the style of error responses used by your API. From 07ad0474c0cef8f8e88d299eca9dffbe6d01c10d Mon Sep 17 00:00:00 2001 From: Ryan Gaffney Date: Tue, 6 Jan 2015 14:34:36 -0800 Subject: [PATCH 04/35] Fix compatibility comment regarding OrderedDict --- rest_framework/compat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index ba26a3cd7..b1f6f2fa6 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -36,7 +36,7 @@ def unicode_to_repr(value): # OrderedDict only available in Python 2.7. # This will always be the case in Django 1.7 and above, as these versions # no longer support Python 2.6. -# For Django <= 1.6 and Python 2.6 fall back to OrderedDict. +# For Django <= 1.6 and Python 2.6 fall back to SortedDict. try: from collections import OrderedDict except ImportError: From fe92a2cfee9e3a20e913500802d98a15e8b70780 Mon Sep 17 00:00:00 2001 From: JocelynDelalande Date: Wed, 7 Jan 2015 10:42:11 +0100 Subject: [PATCH 05/35] fixed doc : DEFAULT_AUTHENTICATION_CLASSES -> DEFAULT_AUTHENTICATION + It is consistent with docs about DEFAULT_PERMISSION_CLASSES --- docs/api-guide/authentication.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api-guide/authentication.md b/docs/api-guide/authentication.md index b04858e39..1222dbf04 100755 --- a/docs/api-guide/authentication.md +++ b/docs/api-guide/authentication.md @@ -34,7 +34,7 @@ The value of `request.user` and `request.auth` for unauthenticated requests can ## Setting the authentication scheme -The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION` setting. For example. +The default authentication schemes may be set globally, using the `DEFAULT_AUTHENTICATION_CLASSES` setting. For example. REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( @@ -282,7 +282,7 @@ This authentication class depends on the optional [django-oauth2-provider][djang 'provider.oauth2', ) -Then add `OAuth2Authentication` to your global `DEFAULT_AUTHENTICATION` setting: +Then add `OAuth2Authentication` to your global `DEFAULT_AUTHENTICATION_CLASSES` setting: 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.OAuth2Authentication', From 42f1932b520a90ae6f8e11246a0992e5f8983bd7 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Wed, 7 Jan 2015 19:10:22 +0100 Subject: [PATCH 06/35] Release notes for 3.0.3 --- docs/topics/release-notes.md | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index b9216e36f..18a47b71b 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -40,6 +40,26 @@ You can determine your currently installed version using `pip freeze`: ## 3.0.x series + +### 3.0.3 + +**Date**: [8th January 2015][3.0.3-milestone]. + +* Fix `MinValueValidator` on `models.DateField`. ([#2369][gh2369]) +* Fix serializer missing context when pagination is used. ([#2355][gh2355]) +* Namespaced router URLs are now supported by the `DefaultRouter`. ([#2351][gh2351]) +* `required=False` allows omission of value for output. ([#2342][gh2342]) +* Use textarea input for `models.TextField`. ([#2340][gh2340]) +* Use custom `ListSerializer` for pagination if required. ([#2331][gh2331], [#2327][gh2327]) +* Better behavior with null and '' for blank HTML fields. ([#2330][gh2330]) +* Ensure fields in `exclude` are model fields. ([#2319][gh2319]) +* Fix `IntegerField` and `max_length` argument incompatibility. ([#2317][gh2317]) +* Fix the YAML encoder for 3.0 serializers. ([#2315][gh2315], [#2283][gh2283]) +* Fix the behavior of empty HTML fields. ([#2311][gh2311], [#1101][gh1101]) +* Fix Metaclass attribute depth ignoring fields attribute. ([#2287][gh2287]) +* Fix `format_suffix_patterns` to work with Django's `i18n_patterns`. ([#2278][gh2278]) +* Ability to customize router URLs for custom actions, using `url_path`. ([#2010][gh2010]) + ### 3.0.2 **Date**: [17th December 2014][3.0.2-milestone]. @@ -729,3 +749,21 @@ For older release notes, [please see the GitHub repo](old-release-notes). [gh2290]: https://github.com/tomchristie/django-rest-framework/issues/2290 [gh2291]: https://github.com/tomchristie/django-rest-framework/issues/2291 [gh2294]: https://github.com/tomchristie/django-rest-framework/issues/2294 + +[gh1101]: https://github.com/tomchristie/django-rest-framework/issues/1101 +[gh2010]: https://github.com/tomchristie/django-rest-framework/issues/2010 +[gh2278]: https://github.com/tomchristie/django-rest-framework/issues/2278 +[gh2283]: https://github.com/tomchristie/django-rest-framework/issues/2283 +[gh2287]: https://github.com/tomchristie/django-rest-framework/issues/2287 +[gh2311]: https://github.com/tomchristie/django-rest-framework/issues/2311 +[gh2315]: https://github.com/tomchristie/django-rest-framework/issues/2315 +[gh2317]: https://github.com/tomchristie/django-rest-framework/issues/2317 +[gh2319]: https://github.com/tomchristie/django-rest-framework/issues/2319 +[gh2327]: https://github.com/tomchristie/django-rest-framework/issues/2327 +[gh2330]: https://github.com/tomchristie/django-rest-framework/issues/2330 +[gh2331]: https://github.com/tomchristie/django-rest-framework/issues/2331 +[gh2340]: https://github.com/tomchristie/django-rest-framework/issues/2340 +[gh2342]: https://github.com/tomchristie/django-rest-framework/issues/2342 +[gh2351]: https://github.com/tomchristie/django-rest-framework/issues/2351 +[gh2355]: https://github.com/tomchristie/django-rest-framework/issues/2355 +[gh2369]: https://github.com/tomchristie/django-rest-framework/issues/2369 From b7015ea8989d67617d276829ccb6a192362ee01f Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Wed, 7 Jan 2015 19:11:17 +0100 Subject: [PATCH 07/35] Bumped the version to 3.0.3. --- rest_framework/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index dec89b3e9..fdcebb7b7 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.0.2' +__version__ = '3.0.3' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2015 Tom Christie' From 60f5b5d9f364c383662fb6ae8d210f31e9621c09 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Wed, 7 Jan 2015 19:19:33 +0100 Subject: [PATCH 08/35] Make Django REST Framework as zip unsafe. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 1e54836c1..efe39d8d4 100755 --- a/setup.py +++ b/setup.py @@ -67,6 +67,7 @@ setup( packages=get_packages('rest_framework'), package_data=get_package_data('rest_framework'), install_requires=[], + zip_safe=False, classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Web Environment', From 1102e22cb407b9069ce3301bd578ba45a775a89e Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 7 Jan 2015 21:02:42 +0000 Subject: [PATCH 09/35] Update project-management.md --- docs/topics/project-management.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/topics/project-management.md b/docs/topics/project-management.md index f581cabd3..037b71827 100644 --- a/docs/topics/project-management.md +++ b/docs/topics/project-management.md @@ -58,6 +58,8 @@ The following template should be used for the description of the issue, and serv #### New members. If you wish to be considered for this or a future date, please comment against this or subsequent issues. + + To modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. #### Responsibilities of team members @@ -107,6 +109,8 @@ The following template should be used for the description of the issue, and serv - [ ] Make a release announcement on the [discussion group](https://groups.google.com/forum/?fromgroups#!forum/django-rest-framework). - [ ] Make a release announcement on twitter. - [ ] Close the milestone on GitHub. + + To modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. When pushing the release to PyPI ensure that your environment has been installed from our development `requirement.txt`, so that documentation and PyPI installs are consistently being built against a pinned set of packages. From 18cefad3abfa6e6a7bbd278e8d54eef66a1d1e53 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 7 Jan 2015 21:03:50 +0000 Subject: [PATCH 10/35] Update project-management.md --- docs/topics/project-management.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/topics/project-management.md b/docs/topics/project-management.md index 037b71827..bcc0330e5 100644 --- a/docs/topics/project-management.md +++ b/docs/topics/project-management.md @@ -59,7 +59,7 @@ The following template should be used for the description of the issue, and serv If you wish to be considered for this or a future date, please comment against this or subsequent issues. - To modify this process for future releases make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. + To modify this process for future maintenance cycles make a pull request to the [project management](http://www.django-rest-framework.org/topics/project-management/) documentation. #### Responsibilities of team members From e61ef3d39f301bc62323b47af5080877e273c395 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 11:07:47 +0000 Subject: [PATCH 11/35] Minor docs updates --- docs/api-guide/filtering.md | 1 + docs/topics/project-management.md | 1 + 2 files changed, 2 insertions(+) diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 83977048f..3eb1538f1 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -316,6 +316,7 @@ Typically you'd instead control this by setting `order_by` on the initial querys queryset = User.objects.all() serializer_class = UserSerializer filter_backends = (filters.OrderingFilter,) + ordering_fields = ('username', 'email') ordering = ('username',) The `ordering` attribute may be either a string or a list/tuple of strings. diff --git a/docs/topics/project-management.md b/docs/topics/project-management.md index f581cabd3..f052aa83a 100644 --- a/docs/topics/project-management.md +++ b/docs/topics/project-management.md @@ -126,6 +126,7 @@ The following issues still need to be addressed: * Ensure `@jamie` has back-up access to the `django-rest-framework.org` domain setup and admin. * Document ownership of the [live example][sandbox] API. * Document ownership of the [mailing list][mailing-list] and IRC channel. +* Document ownership and management of the security mailing list. [bus-factor]: http://en.wikipedia.org/wiki/Bus_factor [un-triaged]: https://github.com/tomchristie/django-rest-framework/issues?q=is%3Aopen+no%3Alabel From b33a6cbff16e5a28a1a696e2ac617303da181720 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 14:16:58 +0000 Subject: [PATCH 12/35] Ensure urlparse is not publically exposed in compat.py - less chance of accidental conflict. --- rest_framework/compat.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index b1f6f2fa6..971dee9cf 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -10,7 +10,7 @@ import inspect from django.core.exceptions import ImproperlyConfigured from django.utils.encoding import force_text -from django.utils.six.moves.urllib import parse as urlparse +from django.utils.six.moves.urllib.parse import urlparse as _urlparse from django.conf import settings from django.utils import six import django @@ -182,7 +182,7 @@ except ImportError: class RequestFactory(DjangoRequestFactory): def generic(self, method, path, data='', content_type='application/octet-stream', **extra): - parsed = urlparse.urlparse(path) + parsed = _urlparse(path) data = force_bytes_or_smart_bytes(data, settings.DEFAULT_CHARSET) r = { 'PATH_INFO': self._get_path(parsed), From f529f83d3c96ca1957d7a8bfc74bd33151cc8d86 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 14:38:23 +0000 Subject: [PATCH 13/35] Minimum Django 1.5 version issue 1.5.6 --- README.md | 2 +- docs/index.md | 2 +- tox.ini | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 8fc11c30f..428a2e56b 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (2.6.5+, 2.7, 3.2, 3.3, 3.4) -* Django (1.4.11+, 1.5.5+, 1.6, 1.7) +* Django (1.4.11+, 1.5.6+, 1.6, 1.7) # Installation diff --git a/docs/index.md b/docs/index.md index 55129df18..a621e3ecb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -51,7 +51,7 @@ Some reasons you might want to use REST framework: REST framework requires the following: * Python (2.6.5+, 2.7, 3.2, 3.3, 3.4) -* Django (1.4.11+, 1.5.5+, 1.6, 1.7) +* Django (1.4.11+, 1.5.6+, 1.6, 1.7) The following packages are optional: diff --git a/tox.ini b/tox.ini index 933ee560e..ab258f2ee 100644 --- a/tox.ini +++ b/tox.ini @@ -11,7 +11,7 @@ setenv = PYTHONDONTWRITEBYTECODE=1 deps = django14: Django==1.4.11 - django15: Django==1.5.5 + django15: Django==1.5.6 django16: Django==1.6.8 django17: Django==1.7.1 djangomaster: https://github.com/django/django/zipball/master From 42c913334b0b4cd731011a07a49ff08aa03d7768 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 14:51:08 +0000 Subject: [PATCH 14/35] Minimum 1.6.x version is 1.6.3 --- README.md | 2 +- docs/index.md | 2 +- tox.ini | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 428a2e56b..cf3dc8576 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ There is a live example API for testing purposes, [available here][sandbox]. # Requirements * Python (2.6.5+, 2.7, 3.2, 3.3, 3.4) -* Django (1.4.11+, 1.5.6+, 1.6, 1.7) +* Django (1.4.11+, 1.5.6+, 1.6.3+, 1.7) # Installation diff --git a/docs/index.md b/docs/index.md index a621e3ecb..d40f8972f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -51,7 +51,7 @@ Some reasons you might want to use REST framework: REST framework requires the following: * Python (2.6.5+, 2.7, 3.2, 3.3, 3.4) -* Django (1.4.11+, 1.5.6+, 1.6, 1.7) +* Django (1.4.11+, 1.5.6+, 1.6.3+, 1.7) The following packages are optional: diff --git a/tox.ini b/tox.ini index ab258f2ee..db2b5d13e 100644 --- a/tox.ini +++ b/tox.ini @@ -10,10 +10,10 @@ commands = ./runtests.py --fast setenv = PYTHONDONTWRITEBYTECODE=1 deps = - django14: Django==1.4.11 - django15: Django==1.5.6 - django16: Django==1.6.8 - django17: Django==1.7.1 + django14: Django==1.4.11 # Should track minimum supported + django15: Django==1.5.6 # Should track minimum supported + django16: Django==1.6.3 # Should track minimum supported + django17: Django==1.7.3 # Should track maximum supported djangomaster: https://github.com/django/django/zipball/master {py26,py27}-django{14,15,16,17}: django-guardian==1.2.3 {py26,py27}-django{14,15,16}: oauth2==1.5.211 From 08008669886f682ba62c4d377f4d96f64808d4a5 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 14:54:54 +0000 Subject: [PATCH 15/35] Fix broken 1.7.3. It's 1.7.2 - 1.7.3 is documented but not yet on PyPI. --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index db2b5d13e..4b90c3929 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,7 @@ deps = django14: Django==1.4.11 # Should track minimum supported django15: Django==1.5.6 # Should track minimum supported django16: Django==1.6.3 # Should track minimum supported - django17: Django==1.7.3 # Should track maximum supported + django17: Django==1.7.2 # Should track maximum supported djangomaster: https://github.com/django/django/zipball/master {py26,py27}-django{14,15,16,17}: django-guardian==1.2.3 {py26,py27}-django{14,15,16}: oauth2==1.5.211 From 4d9e7a53565f6301b87999e6bafdb1c2c3c2af3b Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Thu, 8 Jan 2015 15:38:27 +0000 Subject: [PATCH 16/35] Ammend docstring to use python2/3 compatible example. --- rest_framework/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/settings.py b/rest_framework/settings.py index 33f848138..fc6dfecda 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -167,7 +167,7 @@ class APISettings(object): For example: from rest_framework.settings import api_settings - print api_settings.DEFAULT_RENDERER_CLASSES + print(api_settings.DEFAULT_RENDERER_CLASSES) Any setting with string import paths will be automatically resolved and return the class, rather than the string literal. From ef16c546d77d36bbddacf9b66626f7eaf9f4ff17 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Thu, 8 Jan 2015 23:29:51 +0100 Subject: [PATCH 17/35] Update the release note with latest fixes. Add the link to the 3.0.3 milestone. --- docs/topics/release-notes.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 18a47b71b..c49dd62c9 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -59,6 +59,7 @@ You can determine your currently installed version using `pip freeze`: * Fix Metaclass attribute depth ignoring fields attribute. ([#2287][gh2287]) * Fix `format_suffix_patterns` to work with Django's `i18n_patterns`. ([#2278][gh2278]) * Ability to customize router URLs for custom actions, using `url_path`. ([#2010][gh2010]) +* Don't install Django REST Framework as egg. ([#2386][gh2386]) ### 3.0.2 @@ -700,6 +701,7 @@ For older release notes, [please see the GitHub repo](old-release-notes). [3.0.1-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.1+Release%22 [3.0.2-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.2+Release%22 +[3.0.3-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.3+Release%22 [gh2013]: https://github.com/tomchristie/django-rest-framework/issues/2013 @@ -767,3 +769,4 @@ For older release notes, [please see the GitHub repo](old-release-notes). [gh2351]: https://github.com/tomchristie/django-rest-framework/issues/2351 [gh2355]: https://github.com/tomchristie/django-rest-framework/issues/2355 [gh2369]: https://github.com/tomchristie/django-rest-framework/issues/2369 +[gh2386]: https://github.com/tomchristie/django-rest-framework/issues/2386 From 8ccf5bcc0bb3455c0d71a0e0d845ef54489bb28e Mon Sep 17 00:00:00 2001 From: Travis Swientek Date: Fri, 9 Jan 2015 11:36:21 -0800 Subject: [PATCH 18/35] Tweaked a few issues in the tutorial documentation. --- docs/tutorial/1-serialization.md | 2 +- docs/tutorial/3-class-based-views.md | 2 +- docs/tutorial/4-authentication-and-permissions.md | 2 +- docs/tutorial/5-relationships-and-hyperlinked-apis.md | 2 ++ 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/1-serialization.md b/docs/tutorial/1-serialization.md index 60a3d9897..41ff4d073 100644 --- a/docs/tutorial/1-serialization.md +++ b/docs/tutorial/1-serialization.md @@ -191,7 +191,7 @@ Our `SnippetSerializer` class is replicating a lot of information that's also co In the same way that Django provides both `Form` classes and `ModelForm` classes, REST framework includes both `Serializer` classes, and `ModelSerializer` classes. Let's look at refactoring our serializer using the `ModelSerializer` class. -Open the file `snippets/serializers.py` again, and edit the `SnippetSerializer` class. +Open the file `snippets/serializers.py` again, and replace the `SnippetSerializer` class with the following. class SnippetSerializer(serializers.ModelSerializer): class Meta: diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md index 0a9ea3f15..abf82e495 100644 --- a/docs/tutorial/3-class-based-views.md +++ b/docs/tutorial/3-class-based-views.md @@ -64,7 +64,7 @@ That's looking good. Again, it's still pretty similar to the function based vie We'll also need to refactor our `urls.py` slightly now we're using class based views. - from django.conf.urls import patterns, url + from django.conf.urls import url from rest_framework.urlpatterns import format_suffix_patterns from snippets import views diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 592c77e81..887d1e56f 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -177,7 +177,7 @@ In the snippets app, create a new file, `permissions.py` # Write permissions are only allowed to the owner of the snippet. return obj.owner == request.user -Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetDetail` class: +Now we can add that custom permission to our snippet instance endpoint, by editing the `permission_classes` property on the `SnippetDetail` view class: permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,) diff --git a/docs/tutorial/5-relationships-and-hyperlinked-apis.md b/docs/tutorial/5-relationships-and-hyperlinked-apis.md index c21efd7f6..2841f03e9 100644 --- a/docs/tutorial/5-relationships-and-hyperlinked-apis.md +++ b/docs/tutorial/5-relationships-and-hyperlinked-apis.md @@ -106,6 +106,8 @@ If we're going to have a hyperlinked API, we need to make sure we name our URL p After adding all those names into our URLconf, our final `snippets/urls.py` file should look something like this: + from django.conf.urls import url, include + # API endpoints urlpatterns = format_suffix_patterns([ url(r'^$', views.api_root), From 50b206d3739660cdf089b0a3f8a5bb21d6970e00 Mon Sep 17 00:00:00 2001 From: Steven Loria Date: Sat, 10 Jan 2015 10:17:37 -0600 Subject: [PATCH 19/35] Fix broken links in README --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index cf3dc8576..74bcaeefa 100644 --- a/README.md +++ b/README.md @@ -190,18 +190,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [sandbox]: http://restframework.herokuapp.com/ [index]: http://www.django-rest-framework.org/ -[oauth1-section]: http://www.django-rest-framework.org/api-guide/authentication.html#oauthauthentication -[oauth2-section]: http://www.django-rest-framework.org/api-guide/authentication.html#oauth2authentication -[serializer-section]: http://www.django-rest-framework.org/api-guide/serializers.html#serializers -[modelserializer-section]: http://www.django-rest-framework.org/api-guide/serializers.html#modelserializer -[functionview-section]: http://www.django-rest-framework.org/api-guide/views.html#function-based-views -[generic-views]: http://www.django-rest-framework.org/api-guide/generic-views.html -[viewsets]: http://www.django-rest-framework.org/api-guide/viewsets.html -[routers]: http://www.django-rest-framework.org/api-guide/routers.html -[serializers]: http://www.django-rest-framework.org/api-guide/serializers.html -[authentication]: http://www.django-rest-framework.org/api-guide/authentication.html +[oauth1-section]: http://www.django-rest-framework.org/api-guide/authentication/#oauthauthentication +[oauth2-section]: http://www.django-rest-framework.org/api-guide/authentication/#oauth2authentication +[serializer-section]: http://www.django-rest-framework.org/api-guide/serializers/#serializers +[modelserializer-section]: http://www.django-rest-framework.org/api-guide/serializers/#modelserializer +[functionview-section]: http://www.django-rest-framework.org/api-guide/views/#function-based-views +[generic-views]: http://www.django-rest-framework.org/api-guide/generic-views/ +[viewsets]: http://www.django-rest-framework.org/api-guide/viewsets/ +[routers]: http://www.django-rest-framework.org/api-guide/routers/ +[serializers]: http://www.django-rest-framework.org/api-guide/serializers/ +[authentication]: http://www.django-rest-framework.org/api-guide/authentication/ -[rest-framework-2-announcement]: http://www.django-rest-framework.org/topics/rest-framework-2-announcement.html +[rest-framework-2-announcement]: http://www.django-rest-framework.org/topics/rest-framework-2-announcement [2.1.0-notes]: https://groups.google.com/d/topic/django-rest-framework/Vv2M0CMY9bg/discussion [image]: http://www.django-rest-framework.org/img/quickstart.png From d6bff10f9829b3cef1c2773c303b172a8c7ec525 Mon Sep 17 00:00:00 2001 From: Ask Holme Date: Sat, 10 Jan 2015 18:15:21 +0100 Subject: [PATCH 20/35] Make FileUploadParser work with standard django API Output from parsers ends up in a Django MergeDict and they exists elements to be dicts - not None --- rest_framework/parsers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py index 3e3395c0c..401856ec4 100644 --- a/rest_framework/parsers.py +++ b/rest_framework/parsers.py @@ -277,7 +277,7 @@ class FileUploadParser(BaseParser): for index, handler in enumerate(upload_handlers): file_obj = handler.file_complete(counters[index]) if file_obj: - return DataAndFiles(None, {'file': file_obj}) + return DataAndFiles({}, {'file': file_obj}) raise ParseError("FileUpload parse error - " "none of upload handlers can handle the stream") From d6d08db0dd16f4a4a93b69ecf1c5948f375335b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jose=CC=81=20Padilla?= Date: Sun, 11 Jan 2015 10:55:56 -0400 Subject: [PATCH 21/35] Fix ident format when using HTTP_X_FORWARDED_FOR If NUM_PROXIES setting is set to None, HTTP_X_FORWARDED_FOR might be used as is, which might contain spaces and cause errors on cache backends like memcached. --- rest_framework/throttling.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py index 361dbddf0..7dfe2f967 100644 --- a/rest_framework/throttling.py +++ b/rest_framework/throttling.py @@ -35,7 +35,7 @@ class BaseThrottle(object): client_addr = addrs[-min(num_proxies, len(xff))] return client_addr.strip() - return xff if xff else remote_addr + return ''.join(xff.split()) if xff else remote_addr def wait(self): """ @@ -173,12 +173,6 @@ class AnonRateThrottle(SimpleRateThrottle): if request.user.is_authenticated(): return None # Only throttle unauthenticated requests. - ident = request.META.get('HTTP_X_FORWARDED_FOR') - if ident is None: - ident = request.META.get('REMOTE_ADDR') - else: - ident = ''.join(ident.split()) - return self.cache_format % { 'scope': self.scope, 'ident': self.get_ident(request) From cc13ee0577fb3de9602da634ab9c835749da49c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Padilla?= Date: Mon, 12 Jan 2015 08:12:24 -0400 Subject: [PATCH 22/35] Fix error when NUM_PROXIES is greater than one --- rest_framework/throttling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py index 7dfe2f967..0f10136d6 100644 --- a/rest_framework/throttling.py +++ b/rest_framework/throttling.py @@ -32,7 +32,7 @@ class BaseThrottle(object): if num_proxies == 0 or xff is None: return remote_addr addrs = xff.split(',') - client_addr = addrs[-min(num_proxies, len(xff))] + client_addr = addrs[-min(num_proxies, len(addrs))] return client_addr.strip() return ''.join(xff.split()) if xff else remote_addr From 7f9a62a5bf6a86c4d0a96e5f00d7e96b22d3337f Mon Sep 17 00:00:00 2001 From: Philip Neustrom Date: Tue, 13 Jan 2015 15:19:52 +0800 Subject: [PATCH 23/35] Fix link to `django-rest-framework-filters` (formerly `django-rest-framework-chain`) --- docs/api-guide/filtering.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api-guide/filtering.md b/docs/api-guide/filtering.md index 07420d842..2b6d54492 100644 --- a/docs/api-guide/filtering.md +++ b/docs/api-guide/filtering.md @@ -388,9 +388,9 @@ We could achieve the same behavior by overriding `get_queryset()` on the views, The following third party packages provide additional filter implementations. -## Django REST framework chain +## Django REST framework filters package -The [django-rest-framework-chain package][django-rest-framework-chain] works together with the `DjangoFilterBackend` class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field. +The [django-rest-framework-filters package][django-rest-framework-filters] works together with the `DjangoFilterBackend` class, and allows you to easily create filters across relationships, or create multiple filter lookup types for a given field. [cite]: https://docs.djangoproject.com/en/dev/topics/db/queries/#retrieving-specific-objects-with-filters [django-filter]: https://github.com/alex/django-filter @@ -400,4 +400,4 @@ The [django-rest-framework-chain package][django-rest-framework-chain] works tog [view-permissions-blogpost]: http://blog.nyaruka.com/adding-a-view-permission-to-django-models [nullbooleanselect]: https://github.com/django/django/blob/master/django/forms/widgets.py [search-django-admin]: https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields -[django-rest-framework-chain]: https://github.com/philipn/django-rest-framework-chain +[django-rest-framework-filters]: https://github.com/philipn/django-rest-framework-filters From 4ce4132e08ba7764f120c71eeebdbaefee281689 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Wed, 14 Jan 2015 12:56:03 +0000 Subject: [PATCH 24/35] Preserve ordering on relationship drop-down choices. Closes #2408. --- rest_framework/relations.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/rest_framework/relations.py b/rest_framework/relations.py index 7b119291d..aa0c2defe 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -7,6 +7,7 @@ from django.utils import six from django.utils.encoding import smart_text from django.utils.six.moves.urllib import parse as urlparse from django.utils.translation import ugettext_lazy as _ +from rest_framework.compat import OrderedDict from rest_framework.fields import get_attribute, empty, Field from rest_framework.reverse import reverse from rest_framework.utils import html @@ -103,7 +104,7 @@ class RelatedField(Field): @property def choices(self): - return dict([ + return OrderedDict([ ( six.text_type(self.to_representation(item)), six.text_type(item) @@ -364,7 +365,7 @@ class ManyRelatedField(Field): (item, self.child_relation.to_representation(item)) for item in iterable ] - return dict([ + return OrderedDict([ ( six.text_type(item_representation), six.text_type(item) + ' - ' + six.text_type(item_representation) From 7c0d14a6d56a0813a8abf6da53622c323a77bca8 Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 13:55:53 -0800 Subject: [PATCH 25/35] Bump pytest-django version to 2.8.0 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 48b29e61f..d5b32bfa4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ Django>=1.4.11 # Test requirements -pytest-django==2.6 +pytest-django==2.8.0 pytest==2.5.2 pytest-cov==1.6 flake8==2.2.2 From 00449dc42c11b5795b05885c7a1160dd36501668 Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 13:56:52 -0800 Subject: [PATCH 26/35] Bump pytest version to 2.6.4 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d5b32bfa4..43e947c43 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,7 +3,7 @@ Django>=1.4.11 # Test requirements pytest-django==2.8.0 -pytest==2.5.2 +pytest==2.6.4 pytest-cov==1.6 flake8==2.2.2 From eb91076886466af9376da753b34883b9dc2a1705 Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 14:45:01 -0800 Subject: [PATCH 27/35] Bump pytest-django version in tox.ini to 2.8.0 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4b90c3929..9018b0404 100644 --- a/tox.ini +++ b/tox.ini @@ -20,7 +20,7 @@ deps = {py26,py27}-django{14,15,16}: django-oauth-plus==2.2.1 {py26,py27}-django{14,15}: django-oauth2-provider==0.2.3 {py26,py27}-django16: django-oauth2-provider==0.2.4 - pytest-django==2.6.1 + pytest-django==2.8.0 django-filter==0.7 defusedxml==0.3 markdown>=2.1.0 From 1421b057f7ccf496c0e65e89aa3882d614aa7030 Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 14:48:23 -0800 Subject: [PATCH 28/35] Bump pytest version in tox.ini to 2.6.4 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 9018b0404..f30b44ffb 100644 --- a/tox.ini +++ b/tox.ini @@ -28,7 +28,7 @@ deps = [testenv:py27-flake8] deps = - pytest==2.5.2 + pytest==2.6.4 flake8==2.2.2 commands = ./runtests.py --lintonly From a82a4d0a099eea74832ce3d8de376e4dbeb4b266 Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 15:04:50 -0800 Subject: [PATCH 29/35] Add Django 1.8 alpha to test matrix --- .travis.yml | 8 ++++++++ tox.ini | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6191e7e26..996c3ae80 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,6 +21,10 @@ env: - TOX_ENV=py26-django15 - TOX_ENV=py27-django14 - TOX_ENV=py26-django14 + - TOX_ENV=py34-django18alpha + - TOX_ENV=py33-django18alpha + - TOX_ENV=py32-django18alpha + - TOX_ENV=py27-django18alpha - TOX_ENV=py34-djangomaster - TOX_ENV=py33-djangomaster - TOX_ENV=py32-djangomaster @@ -29,6 +33,10 @@ env: matrix: fast_finish: true allow_failures: + - env: TOX_ENV=py34-django18alpha + - env: TOX_ENV=py33-django18alpha + - env: TOX_ENV=py32-django18alpha + - env: TOX_ENV=py27-django18alpha - env: TOX_ENV=py34-djangomaster - env: TOX_ENV=py33-djangomaster - env: TOX_ENV=py32-djangomaster diff --git a/tox.ini b/tox.ini index f30b44ffb..e43a9234f 100644 --- a/tox.ini +++ b/tox.ini @@ -3,7 +3,7 @@ envlist = py27-{flake8,docs}, {py26,py27}-django14, {py26,py27,py32,py33,py34}-django{15,16}, - {py27,py32,py33,py34}-django{17,master} + {py27,py32,py33,py34}-django{17,18alpha,master} [testenv] commands = ./runtests.py --fast @@ -14,6 +14,7 @@ deps = django15: Django==1.5.6 # Should track minimum supported django16: Django==1.6.3 # Should track minimum supported django17: Django==1.7.2 # Should track maximum supported + django18alpha: https://www.djangoproject.com/download/1.8a1/tarball/ djangomaster: https://github.com/django/django/zipball/master {py26,py27}-django{14,15,16,17}: django-guardian==1.2.3 {py26,py27}-django{14,15,16}: oauth2==1.5.211 From b5128ca574d03ea590a198b04043142a3fc7163e Mon Sep 17 00:00:00 2001 From: David Muller Date: Sun, 18 Jan 2015 15:19:11 -0800 Subject: [PATCH 30/35] Save objects before assigning them in InheritedModelSerializationTests; Django 1.8 now throws an error when assigning unsaved objects to Foreign Key, GenericForeignKey, and OneToOneFields --- tests/test_multitable_inheritance.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_multitable_inheritance.py b/tests/test_multitable_inheritance.py index e1b40cc74..15627e1dd 100644 --- a/tests/test_multitable_inheritance.py +++ b/tests/test_multitable_inheritance.py @@ -48,8 +48,8 @@ class InheritedModelSerializationTests(TestCase): Assert that a model with a onetoone field that is the primary key is not treated like a derived model """ - parent = ParentModel(name1='parent name') - associate = AssociatedModel(name='hello', ref=parent) + parent = ParentModel.objects.create(name1='parent name') + associate = AssociatedModel.objects.create(name='hello', ref=parent) serializer = AssociatedModelSerializer(associate) self.assertEqual(set(serializer.data.keys()), set(['name', 'ref'])) From 5484d570cb8214c776273b45320e7d1c73b85a34 Mon Sep 17 00:00:00 2001 From: Fabien Bochu Date: Mon, 19 Jan 2015 10:57:26 +0100 Subject: [PATCH 31/35] Fix timedelta JSON serialization on Python 2.6. --- rest_framework/compat.py | 8 ++++++++ rest_framework/utils/encoders.py | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/rest_framework/compat.py b/rest_framework/compat.py index 971dee9cf..17814136b 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -33,6 +33,14 @@ def unicode_to_repr(value): return value +def total_seconds(timedelta): + # TimeDelta.total_seconds() is only available in Python 2.7 + if hasattr(timedelta, 'total_seconds'): + return timedelta.total_seconds() + else: + return (timedelta.days * 86400.0) + float(timedelta.seconds) + (timedelta.microseconds / 1000000.0) + + # OrderedDict only available in Python 2.7. # This will always be the case in Django 1.7 and above, as these versions # no longer support Python 2.6. diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 73cbe5d8a..104343a44 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -6,7 +6,7 @@ from django.db.models.query import QuerySet from django.utils import six, timezone from django.utils.encoding import force_text from django.utils.functional import Promise -from rest_framework.compat import OrderedDict +from rest_framework.compat import OrderedDict, total_seconds from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList import datetime import decimal @@ -41,7 +41,7 @@ class JSONEncoder(json.JSONEncoder): representation = representation[:12] return representation elif isinstance(obj, datetime.timedelta): - return six.text_type(obj.total_seconds()) + return six.text_type(total_seconds(obj)) elif isinstance(obj, decimal.Decimal): # Serializers will coerce decimals to strings by default. return float(obj) From da1db34a36f6f0cb8722acbbf7c3182e32995ae3 Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 19 Jan 2015 14:18:02 +0000 Subject: [PATCH 32/35] Handle UUID objects in JSONEncoder. Closes #2433. --- rest_framework/utils/encoders.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 104343a44..bf7532711 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -12,6 +12,7 @@ import datetime import decimal import types import json +import uuid class JSONEncoder(json.JSONEncoder): @@ -45,6 +46,8 @@ class JSONEncoder(json.JSONEncoder): elif isinstance(obj, decimal.Decimal): # Serializers will coerce decimals to strings by default. return float(obj) + elif isinstance(obj, uuid.UUID): + return six.text_type(obj) elif isinstance(obj, QuerySet): return tuple(obj) elif hasattr(obj, 'tolist'): From 0dffc46cb71ec868cdbb37187ba03dea7bac4e7a Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 19 Jan 2015 14:21:09 +0000 Subject: [PATCH 33/35] ReturnDict and ReturnList repr as standard dict/list. Closes #2421. --- rest_framework/utils/serializer_helpers.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rest_framework/utils/serializer_helpers.py b/rest_framework/utils/serializer_helpers.py index 65a04d06b..f99606039 100644 --- a/rest_framework/utils/serializer_helpers.py +++ b/rest_framework/utils/serializer_helpers.py @@ -16,6 +16,9 @@ class ReturnDict(OrderedDict): def copy(self): return ReturnDict(self, serializer=self.serializer) + def __repr__(self): + return dict.__repr__(self) + class ReturnList(list): """ @@ -27,6 +30,9 @@ class ReturnList(list): self.serializer = kwargs.pop('serializer') super(ReturnList, self).__init__(*args, **kwargs) + def __repr__(self): + return list.__repr__(self) + class BoundField(object): """ From af05820b1bfc60ceb7cbb35566588a732938cae2 Mon Sep 17 00:00:00 2001 From: Alexander Dutton Date: Mon, 19 Jan 2015 14:23:13 +0000 Subject: [PATCH 34/35] NotImplemented is not an exception `NotImplemented` is a singleton object, not an exception. You should be raising `NotImplementedError` here instead. --- rest_framework/renderers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 634338e9e..ba6c9cc15 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -46,7 +46,7 @@ class BaseRenderer(object): render_style = 'text' def render(self, data, accepted_media_type=None, renderer_context=None): - raise NotImplemented('Renderer class requires .render() to be implemented') + raise NotImplementedError('Renderer class requires .render() to be implemented') class JSONRenderer(BaseRenderer): From 46a3eda08d519c6908ecd1b9c2e13e5fdb773b0c Mon Sep 17 00:00:00 2001 From: Tom Christie Date: Mon, 19 Jan 2015 14:48:13 +0000 Subject: [PATCH 35/35] NotImplemented -> NotImplementedError --- rest_framework/routers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rest_framework/routers.py b/rest_framework/routers.py index 61f3ccab0..827da0340 100644 --- a/rest_framework/routers.py +++ b/rest_framework/routers.py @@ -65,13 +65,13 @@ class BaseRouter(object): If `base_name` is not specified, attempt to automatically determine it from the viewset. """ - raise NotImplemented('get_default_base_name must be overridden') + raise NotImplementedError('get_default_base_name must be overridden') def get_urls(self): """ Return a list of URL patterns, given the registered viewsets. """ - raise NotImplemented('get_urls must be overridden') + raise NotImplementedError('get_urls must be overridden') @property def urls(self):