diff options
| author | Dmitry Mukhin | 2014-08-20 20:04:48 +0400 | 
|---|---|---|
| committer | Dmitry Mukhin | 2014-08-20 20:04:48 +0400 | 
| commit | 3b07d0c9978335e183f369480618b48ff1e1b1ab (patch) | |
| tree | 041027c50d2965da1be7f93b1a6360e07ad976f9 /rest_framework/generics.py | |
| parent | c3891b6e00daa7a92cca1c88599e046f72926bb4 (diff) | |
| parent | 59b47eac14778767a17e56bd8adc0610417f2878 (diff) | |
| download | django-rest-framework-3b07d0c9978335e183f369480618b48ff1e1b1ab.tar.bz2 | |
Merge branch 'master' into set-retry-after
Conflicts:
	tests/test_throttling.py
Diffstat (limited to 'rest_framework/generics.py')
| -rw-r--r-- | rest_framework/generics.py | 98 | 
1 files changed, 55 insertions, 43 deletions
| diff --git a/rest_framework/generics.py b/rest_framework/generics.py index 7bac510f..77deb8e4 100644 --- a/rest_framework/generics.py +++ b/rest_framework/generics.py @@ -25,6 +25,7 @@ def strict_positive_int(integer_string, cutoff=None):          ret = min(ret, cutoff)      return ret +  def get_object_or_404(queryset, *filter_args, **filter_kwargs):      """      Same as Django's standard shortcut, but make sure to raise 404 @@ -43,6 +44,10 @@ class GenericAPIView(views.APIView):      # You'll need to either set these attributes,      # or override `get_queryset()`/`get_serializer_class()`. +    # If you are overriding a view method, it is important that you call +    # `get_queryset()` instead of accessing the `queryset` property directly, +    # as `queryset` will get evaluated only once, and those results are cached +    # for all subsequent requests.      queryset = None      serializer_class = None @@ -90,8 +95,8 @@ class GenericAPIView(views.APIView):              'view': self          } -    def get_serializer(self, instance=None, data=None, -                       files=None, many=False, partial=False): +    def get_serializer(self, instance=None, data=None, files=None, many=False, +                       partial=False, allow_add_remove=False):          """          Return the serializer instance that should be used for validating and          deserializing input, and for serializing output. @@ -99,7 +104,9 @@ class GenericAPIView(views.APIView):          serializer_class = self.get_serializer_class()          context = self.get_serializer_context()          return serializer_class(instance, data=data, files=files, -                                many=many, partial=partial, context=context) +                                many=many, partial=partial, +                                allow_add_remove=allow_add_remove, +                                context=context)      def get_pagination_serializer(self, page):          """ @@ -121,11 +128,11 @@ class GenericAPIView(views.APIView):          deprecated_style = False          if page_size is not None:              warnings.warn('The `page_size` parameter to `paginate_queryset()` ' -                          'is due to be deprecated. ' +                          'is deprecated. '                            'Note that the return style of this method is also '                            'changed, and will simply return a page object '                            'when called without a `page_size` argument.', -                          PendingDeprecationWarning, stacklevel=2) +                          DeprecationWarning, stacklevel=2)              deprecated_style = True          else:              # Determine the required page size. @@ -136,10 +143,10 @@ class GenericAPIView(views.APIView):          if not self.allow_empty:              warnings.warn( -                'The `allow_empty` parameter is due to be deprecated. ' +                'The `allow_empty` parameter is deprecated. '                  'To use `allow_empty=False` style behavior, You should override '                  '`get_queryset()` and explicitly raise a 404 on empty querysets.', -                PendingDeprecationWarning, stacklevel=2 +                DeprecationWarning, stacklevel=2              )          paginator = self.paginator_class(queryset, page_size, @@ -156,10 +163,11 @@ class GenericAPIView(views.APIView):                  raise Http404(_("Page is not 'last', nor can it be converted to an int."))          try:              page = paginator.page(page_number) -        except InvalidPage as e: -            raise Http404(_('Invalid page (%(page_number)s): %(message)s') % { -                                'page_number': page_number, -                                'message': str(e) +        except InvalidPage as exc: +            error_format = _('Invalid page (%(page_number)s): %(message)s') +            raise Http404(error_format % { +                'page_number': page_number, +                'message': str(exc)              })          if deprecated_style: @@ -183,22 +191,27 @@ class GenericAPIView(views.APIView):          """          Returns the list of filter backends that this view requires.          """ -        filter_backends = self.filter_backends or [] +        if self.filter_backends is None: +            filter_backends = [] +        else: +            # Note that we are returning a *copy* of the class attribute, +            # so that it is safe for the view to mutate it if needed. +            filter_backends = list(self.filter_backends) +          if not filter_backends and self.filter_backend:              warnings.warn(                  'The `filter_backend` attribute and `FILTER_BACKEND` setting ' -                'are due to be deprecated in favor of a `filter_backends` ' +                'are deprecated in favor of a `filter_backends` '                  'attribute and `DEFAULT_FILTER_BACKENDS` setting, that take '                  'a *list* of filter backend classes.', -                PendingDeprecationWarning, stacklevel=2 +                DeprecationWarning, stacklevel=2              )              filter_backends = [self.filter_backend] -        return filter_backends +        return filter_backends -    ######################## -    ### The following methods provide default implementations -    ### that you may want to override for more complex cases. +    # The following methods provide default implementations +    # that you may want to override for more complex cases.      def get_paginate_by(self, queryset=None):          """ @@ -211,8 +224,8 @@ class GenericAPIView(views.APIView):          """          if queryset is not None:              warnings.warn('The `queryset` parameter to `get_paginate_by()` ' -                          'is due to be deprecated.', -                          PendingDeprecationWarning, stacklevel=2) +                          'is deprecated.', +                          DeprecationWarning, stacklevel=2)          if self.paginate_by_param:              try: @@ -256,6 +269,10 @@ class GenericAPIView(views.APIView):          This must be an iterable, and may be a queryset.          Defaults to using `self.queryset`. +        This method should always be used rather than accessing `self.queryset` +        directly, as `self.queryset` gets evaluated only once, and those results +        are cached for all subsequent requests. +          You may want to override this if you need to provide different          querysets depending on the incoming request. @@ -267,8 +284,8 @@ class GenericAPIView(views.APIView):          if self.model is not None:              return self.model._default_manager.all() -        raise ImproperlyConfigured("'%s' must define 'queryset' or 'model'" -                                    % self.__class__.__name__) +        error_format = "'%s' must define 'queryset' or 'model'" +        raise ImproperlyConfigured(error_format % self.__class__.__name__)      def get_object(self, queryset=None):          """ @@ -295,16 +312,16 @@ class GenericAPIView(views.APIView):              filter_kwargs = {self.lookup_field: lookup}          elif pk is not None and self.lookup_field == 'pk':              warnings.warn( -                'The `pk_url_kwarg` attribute is due to be deprecated. ' +                'The `pk_url_kwarg` attribute is deprecated. '                  'Use the `lookup_field` attribute instead', -                PendingDeprecationWarning +                DeprecationWarning              )              filter_kwargs = {'pk': pk}          elif slug is not None and self.lookup_field == 'pk':              warnings.warn( -                'The `slug_url_kwarg` attribute is due to be deprecated. ' +                'The `slug_url_kwarg` attribute is deprecated. '                  'Use the `lookup_field` attribute instead', -                PendingDeprecationWarning +                DeprecationWarning              )              filter_kwargs = {self.slug_field: slug}          else: @@ -322,12 +339,11 @@ class GenericAPIView(views.APIView):          return obj -    ######################## -    ### The following are placeholder methods, -    ### and are intended to be overridden. -    ### -    ### The are not called by GenericAPIView directly, -    ### but are used by the mixin methods. +    # The following are placeholder methods, +    # and are intended to be overridden. +    # +    # The are not called by GenericAPIView directly, +    # but are used by the mixin methods.      def pre_save(self, obj):          """ @@ -399,10 +415,8 @@ class GenericAPIView(views.APIView):          return ret -########################################################## -### Concrete view classes that provide method handlers ### -### by composing the mixin classes with the base view. ### -########################################################## +# Concrete view classes that provide method handlers +# by composing the mixin classes with the base view.  class CreateAPIView(mixins.CreateModelMixin,                      GenericAPIView): @@ -517,16 +531,14 @@ class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,          return self.destroy(request, *args, **kwargs) -########################## -### Deprecated classes ### -########################## +# Deprecated classes  class MultipleObjectAPIView(GenericAPIView):      def __init__(self, *args, **kwargs):          warnings.warn( -            'Subclassing `MultipleObjectAPIView` is due to be deprecated. ' +            'Subclassing `MultipleObjectAPIView` is deprecated. '              'You should simply subclass `GenericAPIView` instead.', -            PendingDeprecationWarning, stacklevel=2 +            DeprecationWarning, stacklevel=2          )          super(MultipleObjectAPIView, self).__init__(*args, **kwargs) @@ -534,8 +546,8 @@ class MultipleObjectAPIView(GenericAPIView):  class SingleObjectAPIView(GenericAPIView):      def __init__(self, *args, **kwargs):          warnings.warn( -            'Subclassing `SingleObjectAPIView` is due to be deprecated. ' +            'Subclassing `SingleObjectAPIView` is deprecated. '              'You should simply subclass `GenericAPIView` instead.', -            PendingDeprecationWarning, stacklevel=2 +            DeprecationWarning, stacklevel=2          )          super(SingleObjectAPIView, self).__init__(*args, **kwargs) | 
