aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle2014-07-28 10:11:40 -0700
committerKyle2014-07-28 10:11:40 -0700
commite40ffd60d44d736d7e27ff454cba1905f0becc26 (patch)
treefdededc77ff5a2720dcf96ca79ddfc9835106827
parent48b02f016a827bc254aba2aedb81b472189c2165 (diff)
downloaddjango-rest-framework-e40ffd60d44d736d7e27ff454cba1905f0becc26.tar.bz2
Issue #1707 - Add documentation about the caching of `GenericAPIView.queryset`
to the `queryset` property, `get_queryset()`, and do generic-views.md; remove changes to the viewsets.md documentation from my last commit.
-rwxr-xr-xdocs/api-guide/generic-views.md8
-rw-r--r--docs/api-guide/viewsets.md15
-rw-r--r--rest_framework/generics.py8
3 files changed, 15 insertions, 16 deletions
diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md
index 7d06f246..b76c18cf 100755
--- a/docs/api-guide/generic-views.md
+++ b/docs/api-guide/generic-views.md
@@ -43,6 +43,12 @@ For more complex cases you might also want to override various methods on the vi
return 20
return 100
+ def list(self, request):
+ # Note the use of `get_queryset()` instead of `self.queryset`
+ queryset = self.get_queryset()
+ serializer = UserSerializer(queryset, many=True)
+ return Response(serializer.data)
+
For very simple cases you might want to pass through any class attributes using the `.as_view()` method. For example, your URLconf might include something the following entry.
url(r'^/users/', ListCreateAPIView.as_view(model=User), name='user-list')
@@ -63,7 +69,7 @@ Each of the concrete generic views provided is built by combining `GenericAPIVie
The following attributes control the basic view behavior.
-* `queryset` - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the `get_queryset()` method.
+* `queryset` - The queryset that should be used for returning objects from this view. Typically, you must either set this attribute, or override the `get_queryset()` method. If you are overriding a view method, it is important that you call `get_queryset()` instead of accessing this property directly, as `queryset` will get evaluated once, and those results will be cached for all subsequent requests.
* `serializer_class` - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the `get_serializer_class()` method.
* `lookup_field` - The model field that should be used to for performing object lookup of individual model instances. Defaults to `'pk'`. Note that when using hyperlinked APIs you'll need to ensure that *both* the API views *and* the serializer classes set the lookup fields if you need to use a custom value.
* `lookup_url_kwarg` - The URL keyword argument that should be used for object lookup. The URL conf should include a keyword argument corresponding to this value. If unset this defaults to using the same value as `lookup_field`.
diff --git a/docs/api-guide/viewsets.md b/docs/api-guide/viewsets.md
index 774e11b7..4f345abb 100644
--- a/docs/api-guide/viewsets.md
+++ b/docs/api-guide/viewsets.md
@@ -70,21 +70,6 @@ There are two main advantages of using a `ViewSet` class over using a `View` cla
Both of these come with a trade-off. Using regular views and URL confs is more explicit and gives you more control. ViewSets are helpful if you want to get up and running quickly, or when you have a large API and you want to enforce a consistent URL configuration throughout.
-## Overriding ModelViewSet Methods
-
-Overriding the ModelViewSet is the same as overriding anything else, except you will need to remember to clone `self.queryset` before you use it, which you can do by using the built-in `get_queryset` method. For example:
-
- class UserViewSet(viewsets.ModelViewSet):
- """
- A viewset for viewing and editing user instances.
- """
- queryset = User.objects.all()
-
- def list(self, request):
- queryset = self.get_queryset()
- serializer = UserSerializer(queryset, many=True)
- return Response(serializer.data)
-
## Marking extra methods for routing
The default routers included with REST framework will provide routes for a standard set of create/retrieve/update/destroy style operations, as shown below:
diff --git a/rest_framework/generics.py b/rest_framework/generics.py
index 7bac510f..65ccd952 100644
--- a/rest_framework/generics.py
+++ b/rest_framework/generics.py
@@ -43,6 +43,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
@@ -256,6 +260,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.