aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/routers.md10
-rw-r--r--docs/topics/release-notes.md38
-rw-r--r--rest_framework/__init__.py2
-rw-r--r--rest_framework/authtoken/south_migrations/0001_initial.py2
-rw-r--r--rest_framework/settings.py11
-rw-r--r--tests/test_filters.py16
-rw-r--r--tests/utils.py25
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):