diff options
| -rw-r--r-- | docs/api-guide/routers.md | 10 | ||||
| -rw-r--r-- | docs/topics/release-notes.md | 38 | ||||
| -rw-r--r-- | rest_framework/__init__.py | 2 | ||||
| -rw-r--r-- | rest_framework/authtoken/south_migrations/0001_initial.py | 2 | ||||
| -rw-r--r-- | rest_framework/settings.py | 11 | ||||
| -rw-r--r-- | tests/test_filters.py | 16 | ||||
| -rw-r--r-- | tests/utils.py | 25 |
7 files changed, 69 insertions, 35 deletions
diff --git a/docs/api-guide/routers.md b/docs/api-guide/routers.md index 9c9bfb50..a9f911a9 100644 --- a/docs/api-guide/routers.md +++ b/docs/api-guide/routers.md @@ -60,7 +60,7 @@ For example, you can append `router.urls` to a list of existing views… router.register(r'accounts', AccountViewSet) urlpatterns = [ - url(r'^forgot-password/$', ForgotPasswordFormView.as_view(), + url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), ] urlpatterns += router.urls @@ -68,15 +68,15 @@ For example, you can append `router.urls` to a list of existing views… Alternatively you can use Django's `include` function, like so… urlpatterns = [ - url(r'^forgot-password/$', ForgotPasswordFormView.as_view(), - url(r'^', include(router.urls)) + url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), + url(r'^', include(router.urls)), ] Router URL patterns can also be namespaces. urlpatterns = [ - url(r'^forgot-password/$', ForgotPasswordFormView.as_view(), - url(r'^api/', include(router.urls, namespace='api')) + url(r'^forgot-password/$', ForgotPasswordFormView.as_view()), + url(r'^api/', include(router.urls, namespace='api')), ] If using namespacing with hyperlinked serializers you'll also need to ensure that any `view_name` parameters on the serializers correctly reflect the namespace. In the example above you'd need to include a parameter such as `view_name='api:user-detail'` for serializer fields hyperlinked to the user detail view. diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index c49dd62c..e0894d2d 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -41,6 +41,24 @@ You can determine your currently installed version using `pip freeze`: ## 3.0.x series +### 3.0.4 + +**Date**: [28th January 2015][3.0.4-milestone]. + +* Django 1.8a1 support. ([#2425][gh2425], [#2446][gh2446], [#2441][gh2441]) +* Add `DictField` and support Django 1.8 `HStoreField`. ([#2451][gh2451], [#2106][gh2106]) +* Add `UUIDField` and support Django 1.8 `UUIDField`. ([#2448][gh2448], [#2433][gh2433], [#2432][gh2432]) +* `BaseRenderer.render` now raises `NotImplementedError`. ([#2434][gh2434]) +* Fix timedelta JSON serialization on Python 2.6. ([#2430][gh2430]) +* `ResultDict` and `ResultList` now appear as standard dict/list. ([#2421][gh2421]) +* Fix visible `HiddenField` in the HTML form of the web browsable API page. ([#2410][gh2410]) +* Use `OrderedDict` for `RelatedField.choices`. ([#2408][gh2408]) +* Fix ident format when using `HTTP_X_FORWARDED_FOR`. ([#2401][gh2401]) +* Fix invalid key with memcached while using throttling. ([#2400][gh2400]) +* Fix `FileUploadParser` with version 3.x. ([#2399][gh2399]) +* Fix the serializer inheritance. ([#2388][gh2388]) +* Fix caching issues with `ReturnDict`. ([#2360][gh2360]) + ### 3.0.3 **Date**: [8th January 2015][3.0.3-milestone]. @@ -702,6 +720,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 +[3.0.4-milestone]: https://github.com/tomchristie/django-rest-framework/issues?q=milestone%3A%223.0.4+Release%22 <!-- 3.0.1 --> [gh2013]: https://github.com/tomchristie/django-rest-framework/issues/2013 @@ -770,3 +789,22 @@ For older release notes, [please see the GitHub repo](old-release-notes). [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 +<!-- 3.0.4 --> +[gh2425]: https://github.com/tomchristie/django-rest-framework/issues/2425 +[gh2446]: https://github.com/tomchristie/django-rest-framework/issues/2446 +[gh2441]: https://github.com/tomchristie/django-rest-framework/issues/2441 +[gh2451]: https://github.com/tomchristie/django-rest-framework/issues/2451 +[gh2106]: https://github.com/tomchristie/django-rest-framework/issues/2106 +[gh2448]: https://github.com/tomchristie/django-rest-framework/issues/2448 +[gh2433]: https://github.com/tomchristie/django-rest-framework/issues/2433 +[gh2432]: https://github.com/tomchristie/django-rest-framework/issues/2432 +[gh2434]: https://github.com/tomchristie/django-rest-framework/issues/2434 +[gh2430]: https://github.com/tomchristie/django-rest-framework/issues/2430 +[gh2421]: https://github.com/tomchristie/django-rest-framework/issues/2421 +[gh2410]: https://github.com/tomchristie/django-rest-framework/issues/2410 +[gh2408]: https://github.com/tomchristie/django-rest-framework/issues/2408 +[gh2401]: https://github.com/tomchristie/django-rest-framework/issues/2401 +[gh2400]: https://github.com/tomchristie/django-rest-framework/issues/2400 +[gh2399]: https://github.com/tomchristie/django-rest-framework/issues/2399 +[gh2388]: https://github.com/tomchristie/django-rest-framework/issues/2388 +[gh2360]: https://github.com/tomchristie/django-rest-framework/issues/2360 diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py index fdcebb7b..57e5421b 100644 --- a/rest_framework/__init__.py +++ b/rest_framework/__init__.py @@ -8,7 +8,7 @@ ______ _____ _____ _____ __ """ __title__ = 'Django REST framework' -__version__ = '3.0.3' +__version__ = '3.0.4' __author__ = 'Tom Christie' __license__ = 'BSD 2-Clause' __copyright__ = 'Copyright 2011-2015 Tom Christie' diff --git a/rest_framework/authtoken/south_migrations/0001_initial.py b/rest_framework/authtoken/south_migrations/0001_initial.py index 926de02b..5b927f3e 100644 --- a/rest_framework/authtoken/south_migrations/0001_initial.py +++ b/rest_framework/authtoken/south_migrations/0001_initial.py @@ -40,7 +40,7 @@ class Migration(SchemaMigration): 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) }, "%s.%s" % (User._meta.app_label, User._meta.module_name): { - 'Meta': {'object_name': User._meta.module_name}, + 'Meta': {'object_name': User._meta.module_name, 'db_table': repr(User._meta.db_table)}, }, 'authtoken.token': { 'Meta': {'object_name': 'Token'}, diff --git a/rest_framework/settings.py b/rest_framework/settings.py index fc6dfecd..e5e5edaf 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -18,6 +18,7 @@ REST framework settings, checking for user settings first, then falling back to the defaults. """ from __future__ import unicode_literals +from django.test.signals import setting_changed from django.conf import settings from django.utils import importlib, six from rest_framework import ISO_8601 @@ -198,3 +199,13 @@ class APISettings(object): api_settings = APISettings(USER_SETTINGS, DEFAULTS, IMPORT_STRINGS) + + +def reload_api_settings(*args, **kwargs): + global api_settings + setting, value = kwargs['setting'], kwargs['value'] + if setting == 'REST_FRAMEWORK': + api_settings = APISettings(value, DEFAULTS, IMPORT_STRINGS) + + +setting_changed.connect(reload_api_settings) diff --git a/tests/test_filters.py b/tests/test_filters.py index 5b1b6ca5..355f02ce 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -5,13 +5,15 @@ from django.db import models from django.conf.urls import patterns, url from django.core.urlresolvers import reverse from django.test import TestCase +from django.test.utils import override_settings from django.utils import unittest from django.utils.dateparse import parse_date +from django.utils.six.moves import reload_module from rest_framework import generics, serializers, status, filters from rest_framework.compat import django_filters from rest_framework.test import APIRequestFactory from .models import BaseFilterableItem, FilterableItem, BasicModel -from .utils import temporary_setting + factory = APIRequestFactory() @@ -404,7 +406,9 @@ class SearchFilterTests(TestCase): ) def test_search_with_nonstandard_search_param(self): - with temporary_setting('SEARCH_PARAM', 'query', module=filters): + with override_settings(REST_FRAMEWORK={'SEARCH_PARAM': 'query'}): + reload_module(filters) + class SearchListView(generics.ListAPIView): queryset = SearchFilterModel.objects.all() serializer_class = SearchFilterSerializer @@ -422,6 +426,8 @@ class SearchFilterTests(TestCase): ] ) + reload_module(filters) + class OrderingFilterModel(models.Model): title = models.CharField(max_length=20) @@ -642,7 +648,9 @@ class OrderingFilterTests(TestCase): ) def test_ordering_with_nonstandard_ordering_param(self): - with temporary_setting('ORDERING_PARAM', 'order', filters): + with override_settings(REST_FRAMEWORK={'ORDERING_PARAM': 'order'}): + reload_module(filters) + class OrderingListView(generics.ListAPIView): queryset = OrderingFilterModel.objects.all() serializer_class = OrderingFilterSerializer @@ -662,6 +670,8 @@ class OrderingFilterTests(TestCase): ] ) + reload_module(filters) + class SensitiveOrderingFilterModel(models.Model): username = models.CharField(max_length=20) diff --git a/tests/utils.py b/tests/utils.py index 5e902ba9..5b2d7586 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -1,30 +1,5 @@ -from contextlib import contextmanager from django.core.exceptions import ObjectDoesNotExist from django.core.urlresolvers import NoReverseMatch -from django.utils import six -from rest_framework.settings import api_settings - - -@contextmanager -def temporary_setting(setting, value, module=None): - """ - Temporarily change value of setting for test. - - Optionally reload given module, useful when module uses value of setting on - import. - """ - original_value = getattr(api_settings, setting) - setattr(api_settings, setting, value) - - if module is not None: - six.moves.reload_module(module) - - yield - - setattr(api_settings, setting, original_value) - - if module is not None: - six.moves.reload_module(module) class MockObject(object): |
