Browse Source

Improved queryset handling and docs for (Single|Multiple)ObjectMixin.

Loic Bistuer 11 years ago
parent
commit
f8a6a4eba1

+ 12 - 8
django/views/generic/detail.py

@@ -57,19 +57,23 @@ class SingleObjectMixin(ContextMixin):
 
     def get_queryset(self):
         """
-        Get the queryset to look an object up against. May not be called if
-        `get_object` is overridden.
+        Return the `QuerySet` that will be used to look up the object.
+
+        Note that this method is called by the default implementation of
+        `get_object` and may not be called if `get_object` is overriden.
         """
         if self.queryset is None:
             if self.model:
                 return self.model._default_manager.all()
             else:
-                raise ImproperlyConfigured("%(cls)s is missing a queryset. Define "
-                                           "%(cls)s.model, %(cls)s.queryset, or override "
-                                           "%(cls)s.get_queryset()." % {
-                                                'cls': self.__class__.__name__
-                                        })
-        return self.queryset._clone()
+                raise ImproperlyConfigured(
+                    "%(cls)s is missing a QuerySet. Define "
+                    "%(cls)s.model, %(cls)s.queryset, or override "
+                    "%(cls)s.get_queryset()." % {
+                        'cls': self.__class__.__name__
+                    }
+                )
+        return self.queryset.all()
 
     def get_slug_field(self):
         """

+ 14 - 6
django/views/generic/list.py

@@ -2,6 +2,7 @@ from __future__ import unicode_literals
 
 from django.core.paginator import Paginator, InvalidPage
 from django.core.exceptions import ImproperlyConfigured
+from django.db.models.query import QuerySet
 from django.http import Http404
 from django.utils.translation import ugettext as _
 from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
@@ -22,18 +23,25 @@ class MultipleObjectMixin(ContextMixin):
 
     def get_queryset(self):
         """
-        Get the list of items for this view. This must be an iterable, and may
-        be a queryset (in which qs-specific behavior will be enabled).
+        Return the list of items for this view.
+
+        The return value must be an iterable and may be an instance of
+        `QuerySet` in which case `QuerySet` specific behavior will be enabled.
         """
         if self.queryset is not None:
             queryset = self.queryset
-            if hasattr(queryset, '_clone'):
-                queryset = queryset._clone()
+            if isinstance(queryset, QuerySet):
+                queryset = queryset.all()
         elif self.model is not None:
             queryset = self.model._default_manager.all()
         else:
-            raise ImproperlyConfigured("'%s' must define 'queryset' or 'model'"
-                                       % self.__class__.__name__)
+            raise ImproperlyConfigured(
+                "%(cls)s is missing a QuerySet. Define "
+                "%(cls)s.model, %(cls)s.queryset, or override "
+                "%(cls)s.get_queryset()." % {
+                    'cls': self.__class__.__name__
+                }
+            )
         return queryset
 
     def paginate_queryset(self, queryset, page_size):

+ 8 - 0
docs/ref/class-based-views/mixins-multiple-object.txt

@@ -63,6 +63,14 @@ MultipleObjectMixin
         A ``QuerySet`` that represents the objects. If provided, the value of
         ``queryset`` supersedes the value provided for :attr:`model`.
 
+        .. warning::
+
+            ``queryset`` is a class attribute with a *mutable* value so care
+            must be taken when using it directly. Before using it, either call
+            its :meth:`~django.db.models.query.QuerySet.all` method or
+            retrieve it with :meth:`get_queryset` which takes care of the
+            cloning behind the scenes.
+
     .. attribute:: paginate_by
 
         An integer specifying how many objects should be displayed per page. If

+ 8 - 0
docs/ref/class-based-views/mixins-single-object.txt

@@ -23,6 +23,14 @@ SingleObjectMixin
         A ``QuerySet`` that represents the objects. If provided, the value of
         ``queryset`` supersedes the value provided for :attr:`model`.
 
+        .. warning::
+
+            ``queryset`` is a class attribute with a *mutable* value so care
+            must be taken when using it directly. Before using it, either call
+            its :meth:`~django.db.models.query.QuerySet.all` method or
+            retrieve it with :meth:`get_queryset` which takes care of the
+            cloning behind the scenes.
+
     .. attribute:: slug_field
 
         The name of the field on the model that contains the slug. By default,