diff options
| author | Tom Christie | 2015-02-09 20:43:50 +0000 | 
|---|---|---|
| committer | Tom Christie | 2015-02-09 20:43:50 +0000 | 
| commit | fbb21caaaa01033bbd34b0c63ab48243ffb6310e (patch) | |
| tree | 5d0fdee18c9bf02733b1df913c4cddd9e3e86da7 /rest_framework | |
| parent | 407480b4840990ff17f9a33b293cfcf15bb6f7c5 (diff) | |
| parent | 7b639c0cd0676172cc8502e833f5b708f39f9a83 (diff) | |
| download | django-rest-framework-fbb21caaaa01033bbd34b0c63ab48243ffb6310e.tar.bz2 | |
Merge master
Diffstat (limited to 'rest_framework')
| -rw-r--r-- | rest_framework/authentication.py | 2 | ||||
| -rw-r--r-- | rest_framework/decorators.py | 11 | ||||
| -rw-r--r-- | rest_framework/pagination.py | 4 | ||||
| -rw-r--r-- | rest_framework/request.py | 21 | ||||
| -rw-r--r-- | rest_framework/response.py | 3 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 6 | ||||
| -rw-r--r-- | rest_framework/templatetags/rest_framework.py | 4 | ||||
| -rw-r--r-- | rest_framework/throttling.py | 4 | 
8 files changed, 36 insertions, 19 deletions
| diff --git a/rest_framework/authentication.py b/rest_framework/authentication.py index a75cd30c..f0702286 100644 --- a/rest_framework/authentication.py +++ b/rest_framework/authentication.py @@ -168,7 +168,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/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/pagination.py b/rest_framework/pagination.py index b3658aca..496500ba 100644 --- a/rest_framework/pagination.py +++ b/rest_framework/pagination.py @@ -168,7 +168,9 @@ def _reverse_ordering(ordering_tuple):      Given an order_by tuple such as `('-created', 'uuid')` reverse the      ordering and return a new tuple, eg. `('created', '-uuid')`.      """ -    invert = lambda x: x[1:] if (x.startswith('-')) else '-' + x +    def invert(x): +        return x[1:] if (x.startswith('-')) else '-' + x +      return tuple([invert(item) for item in ordering_tuple]) diff --git a/rest_framework/request.py b/rest_framework/request.py index 86fb1ef1..081ace23 100644 --- a/rest_framework/request.py +++ b/rest_framework/request.py @@ -12,12 +12,13 @@ from __future__ import unicode_literals  from django.conf import settings  from django.http import QueryDict  from django.http.multipartparser import parse_header +from django.utils import six  from django.utils.datastructures import MultiValueDict  from django.utils.datastructures import MergeDict as DjangoMergeDict -from django.utils.six import BytesIO  from rest_framework import HTTP_HEADER_ENCODING  from rest_framework import exceptions  from rest_framework.settings import api_settings +import sys  import warnings @@ -366,7 +367,7 @@ class Request(object):          elif hasattr(self._request, 'read'):              self._stream = self._request          else: -            self._stream = BytesIO(self.raw_post_data) +            self._stream = six.BytesIO(self.raw_post_data)      def _perform_form_overloading(self):          """ @@ -408,7 +409,7 @@ class Request(object):              self._CONTENTTYPE_PARAM in self._data          ):              self._content_type = self._data[self._CONTENTTYPE_PARAM] -            self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode(self.parser_context['encoding'])) +            self._stream = six.BytesIO(self._data[self._CONTENT_PARAM].encode(self.parser_context['encoding']))              self._data, self._files, self._full_data = (Empty, Empty, Empty)      def _parse(self): @@ -489,8 +490,16 @@ class Request(object):          else:              self.auth = None -    def __getattr__(self, attr): +    def __getattribute__(self, attr):          """ -        Proxy other attributes to the underlying HttpRequest object. +        If an attribute does not exist on this instance, then we also attempt +        to proxy it to the underlying HttpRequest object.          """ -        return getattr(self._request, attr) +        try: +            return super(Request, self).__getattribute__(attr) +        except AttributeError: +            info = sys.exc_info() +            try: +                return getattr(self._request, attr) +            except AttributeError: +                six.reraise(info[0], info[1], info[2].tb_next) 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/serializers.py b/rest_framework/serializers.py index 7235d8c5..c60574d4 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.'          ) @@ -635,11 +635,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/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py index a969836f..699ea897 100644 --- a/rest_framework/templatetags/rest_framework.py +++ b/rest_framework/templatetags/rest_framework.py @@ -143,7 +143,9 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru      If autoescape is True, the link text and URLs will get autoescaped.      """ -    trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x +    def trim_url(x, limit=trim_url_limit): +        return limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x +      safe_input = isinstance(text, SafeData)      words = word_split_re.split(force_text(text))      for i, word in enumerate(words): 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) | 
