aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/__init__.py2
-rw-r--r--rest_framework/authentication.py2
-rw-r--r--rest_framework/authtoken/south_migrations/0001_initial.py2
-rw-r--r--rest_framework/decorators.py11
-rw-r--r--rest_framework/relations.py5
-rw-r--r--rest_framework/response.py3
-rw-r--r--rest_framework/routers.py10
-rw-r--r--rest_framework/serializers.py6
-rw-r--r--rest_framework/settings.py11
-rw-r--r--rest_framework/throttling.py4
10 files changed, 35 insertions, 21 deletions
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/authentication.py b/rest_framework/authentication.py
index 4832ad33..f7601fb1 100644
--- a/rest_framework/authentication.py
+++ b/rest_framework/authentication.py
@@ -167,7 +167,7 @@ class TokenAuthentication(BaseAuthentication):
def authenticate_credentials(self, key):
try:
- token = self.model.objects.get(key=key)
+ token = self.model.objects.select_related('user').get(key=key)
except self.model.DoesNotExist:
raise exceptions.AuthenticationFailed('Invalid token')
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/decorators.py b/rest_framework/decorators.py
index 325435b3..21de1acf 100644
--- a/rest_framework/decorators.py
+++ b/rest_framework/decorators.py
@@ -18,8 +18,7 @@ def api_view(http_method_names=None):
Decorator that converts a function-based view into an APIView subclass.
Takes a list of allowed methods for the view as an argument.
"""
- if http_method_names is None:
- http_method_names = ['GET']
+ http_method_names = ['GET'] if (http_method_names is None) else http_method_names
def decorator(func):
@@ -109,10 +108,12 @@ def permission_classes(permission_classes):
return decorator
-def detail_route(methods=['get'], **kwargs):
+def detail_route(methods=None, **kwargs):
"""
Used to mark a method on a ViewSet that should be routed for detail requests.
"""
+ methods = ['get'] if (methods is None) else methods
+
def decorator(func):
func.bind_to_methods = methods
func.detail = True
@@ -121,10 +122,12 @@ def detail_route(methods=['get'], **kwargs):
return decorator
-def list_route(methods=['get'], **kwargs):
+def list_route(methods=None, **kwargs):
"""
Used to mark a method on a ViewSet that should be routed for list requests.
"""
+ methods = ['get'] if (methods is None) else methods
+
def decorator(func):
func.bind_to_methods = methods
func.detail = False
diff --git a/rest_framework/relations.py b/rest_framework/relations.py
index aa0c2def..13793f37 100644
--- a/rest_framework/relations.py
+++ b/rest_framework/relations.py
@@ -338,7 +338,12 @@ class ManyRelatedField(Field):
# We override the default field access in order to support
# lists in HTML forms.
if html.is_html_input(dictionary):
+ # Don't return [] if the update is partial
+ if self.field_name not in dictionary:
+ if getattr(self.root, 'partial', False):
+ return empty
return dictionary.getlist(self.field_name)
+
return dictionary.get(self.field_name, empty)
def to_internal_value(self, data):
diff --git a/rest_framework/response.py b/rest_framework/response.py
index 7f90bae1..c21c60a2 100644
--- a/rest_framework/response.py
+++ b/rest_framework/response.py
@@ -86,8 +86,9 @@ class Response(SimpleTemplateResponse):
state = super(Response, self).__getstate__()
for key in (
'accepted_renderer', 'renderer_context', 'resolver_match',
- 'client', 'request', 'wsgi_request', '_closable_objects'
+ 'client', 'request', 'wsgi_request'
):
if key in state:
del state[key]
+ state['_closable_objects'] = []
return state
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index 827da034..6a4184e2 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -130,19 +130,13 @@ class SimpleRouter(BaseRouter):
If `base_name` is not specified, attempt to automatically determine
it from the viewset.
"""
- # Note that `.model` attribute on views is deprecated, although we
- # enforce the deprecation on the view `get_serializer_class()` and
- # `get_queryset()` methods, rather than here.
- model_cls = getattr(viewset, 'model', None)
queryset = getattr(viewset, 'queryset', None)
- if model_cls is None and queryset is not None:
- model_cls = queryset.model
- assert model_cls, '`base_name` argument not specified, and could ' \
+ assert queryset is not None, '`base_name` argument not specified, and could ' \
'not automatically determine the name from the viewset, as ' \
'it does not have a `.queryset` attribute.'
- return model_cls._meta.object_name.lower()
+ return queryset.model._meta.object_name.lower()
def get_routes(self, viewset):
"""
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 42d1e370..d76658b0 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -177,7 +177,7 @@ class BaseSerializer(Field):
)
assert hasattr(self, 'initial_data'), (
- 'Cannot call `.is_valid()` as no `data=` keyword argument was'
+ 'Cannot call `.is_valid()` as no `data=` keyword argument was '
'passed when instantiating the serializer instance.'
)
@@ -633,11 +633,11 @@ def raise_errors_on_nested_writes(method_name, serializer, validated_data):
If we don't do this explicitly they'd get a less helpful error when
calling `.save()` on the serializer.
- We don't *automatically* support these sorts of nested writes brecause
+ We don't *automatically* support these sorts of nested writes because
there are too many ambiguities to define a default behavior.
Eg. Suppose we have a `UserSerializer` with a nested profile. How should
- we handle the case of an update, where the `profile` realtionship does
+ we handle the case of an update, where the `profile` relationship does
not exist? Any of the following might be valid:
* Raise an application error.
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/rest_framework/throttling.py b/rest_framework/throttling.py
index 0f10136d..261fc246 100644
--- a/rest_framework/throttling.py
+++ b/rest_framework/throttling.py
@@ -191,7 +191,7 @@ class UserRateThrottle(SimpleRateThrottle):
def get_cache_key(self, request, view):
if request.user.is_authenticated():
- ident = request.user.id
+ ident = request.user.pk
else:
ident = self.get_ident(request)
@@ -239,7 +239,7 @@ class ScopedRateThrottle(SimpleRateThrottle):
with the '.throttle_scope` property of the view.
"""
if request.user.is_authenticated():
- ident = request.user.id
+ ident = request.user.pk
else:
ident = self.get_ident(request)