aboutsummaryrefslogtreecommitdiffstats
path: root/docs/tutorial/3-class-based-views.md
diff options
context:
space:
mode:
authorJamie Matthews2012-09-26 13:05:21 +0100
committerJamie Matthews2012-09-26 13:05:21 +0100
commit01770c53cd9045e6ea054f32b1e40b5d2ff7fe44 (patch)
tree657cb66f92d78add3b2f587754387832043168e6 /docs/tutorial/3-class-based-views.md
parentf6488cb0589d3b11fb8d831e00d1389f3fff74b6 (diff)
parent09a445b257532be69ffab69a3f62b84bfa90463d (diff)
downloaddjango-rest-framework-01770c53cd9045e6ea054f32b1e40b5d2ff7fe44.tar.bz2
Merge branch 'restframework2' of git://github.com/tomchristie/django-rest-framework into improved-view-decorators
* 'restframework2' of git://github.com/tomchristie/django-rest-framework: (56 commits) Bits of cleanup Add request.QUERY_PARAMS Add readonly 'id' field Tweak browseable API Don't display readonly fields Fix some bits of serialization Add csrf note Fix incorrect bit of tutorial Added tox.ini Tweak media_type -> accepted_media_type. Need to document, but marginally less confusing Tweak media_type -> accepted_media_type. Need to document, but marginally less confusing Tweak media_type -> accepted_media_type. Need to document, but marginally less confusing Clean up bits of templates etc Hack out bunch of unneccesary private methods on View class Clean up template tags Remove dumbass __all__ variables Remove old 'djangorestframework directories Change package name: djangorestframework -> rest_framework Dont strip final '/' Use get_script_prefix to play nicely if not installed at the root. ... Conflicts: rest_framework/decorators.py
Diffstat (limited to 'docs/tutorial/3-class-based-views.md')
-rw-r--r--docs/tutorial/3-class-based-views.md51
1 files changed, 26 insertions, 25 deletions
diff --git a/docs/tutorial/3-class-based-views.md b/docs/tutorial/3-class-based-views.md
index 24785179..25d5773f 100644
--- a/docs/tutorial/3-class-based-views.md
+++ b/docs/tutorial/3-class-based-views.md
@@ -1,6 +1,6 @@
# Tutorial 3: Class Based Views
-We can also write our API views using class based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code [DRY][1].
+We can also write our API views using class based views, rather than function based views. As we'll see this is a powerful pattern that allows us to reuse common functionality, and helps us keep our code [DRY][dry].
## Rewriting our API using class based views
@@ -9,9 +9,9 @@ We'll start by rewriting the root view as a class based view. All this involves
from blog.models import Comment
from blog.serializers import CommentSerializer
from django.http import Http404
- from djangorestframework.views import APIView
- from djangorestframework.response import Response
- from djangorestframework import status
+ from rest_framework.views import APIView
+ from rest_framework.response import Response
+ from rest_framework import status
class CommentRoot(APIView):
@@ -31,8 +31,6 @@ We'll start by rewriting the root view as a class based view. All this involves
return Response(serializer.serialized, status=status.HTTP_201_CREATED)
return Response(serializer.serialized_errors, status=status.HTTP_400_BAD_REQUEST)
- comment_root = CommentRoot.as_view()
-
So far, so good. It looks pretty similar to the previous case, but we've got better seperation between the different HTTP methods. We'll also need to update the instance view.
class CommentInstance(APIView):
@@ -55,19 +53,31 @@ So far, so good. It looks pretty similar to the previous case, but we've got be
comment = self.get_object(pk)
serializer = CommentSerializer(request.DATA, instance=comment)
if serializer.is_valid():
- comment = serializer.deserialized
+ comment = serializer.object
comment.save()
return Response(serializer.data)
- return Response(serializer.error_data, status=status.HTTP_400_BAD_REQUEST)
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
comment = self.get_object(pk)
comment.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- comment_instance = CommentInstance.as_view()
-
That's looking good. Again, it's still pretty similar to the function based view right now.
+
+We'll also need to refactor our URLconf slightly now we're using class based views.
+
+ from django.conf.urls import patterns, url
+ from rest_framework.urlpatterns import format_suffix_patterns
+ from blogpost import views
+
+ urlpatterns = patterns('',
+ url(r'^$', views.CommentRoot.as_view()),
+ url(r'^(?P<pk>[0-9]+)$', views.CommentInstance.as_view())
+ )
+
+ urlpatterns = format_suffix_patterns(urlpatterns)
+
Okay, we're done. If you run the development server everything should be working just as before.
## Using mixins
@@ -80,8 +90,8 @@ Let's take a look at how we can compose our views by using the mixin classes.
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework import mixins
- from djangorestframework import generics
+ from rest_framework import mixins
+ from rest_framework import generics
class CommentRoot(mixins.ListModelMixin,
mixins.CreateModelMixin,
@@ -95,8 +105,6 @@ Let's take a look at how we can compose our views by using the mixin classes.
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
- comment_root = CommentRoot.as_view()
-
We'll take a moment to examine exactly what's happening here - We're building our view using `MultipleObjectBaseView`, and adding in `ListModelMixin` and `CreateModelMixin`.
The base class provides the core functionality, and the mixin classes provide the `.list()` and `.create()` actions. We're then explictly binding the `get` and `post` methods to the appropriate actions. Simple enough stuff so far.
@@ -117,8 +125,6 @@ The base class provides the core functionality, and the mixin classes provide th
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
- comment_instance = CommentInstance.as_view()
-
Pretty similar. This time we're using the `SingleObjectBaseView` class to provide the core functionality, and adding in mixins to provide the `.retrieve()`, `.update()` and `.destroy()` actions.
## Using generic class based views
@@ -127,26 +133,21 @@ Using the mixin classes we've rewritten the views to use slightly less code than
from blog.models import Comment
from blog.serializers import CommentSerializer
- from djangorestframework import generics
+ from rest_framework import generics
class CommentRoot(generics.RootAPIView):
model = Comment
serializer_class = CommentSerializer
- comment_root = CommentRoot.as_view()
-
class CommentInstance(generics.InstanceAPIView):
model = Comment
serializer_class = CommentSerializer
- comment_instance = CommentInstance.as_view()
-
-
Wow, that's pretty concise. We've got a huge amount for free, and our code looks like good, clean, idomatic Django.
-Next we'll move onto [part 4 of the tutorial][2], where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.
+Next we'll move onto [part 4 of the tutorial][tut-4], where we'll take a look at how we can customize the behavior of our views to support a range of authentication, permissions, throttling and other aspects.
-[1]: http://en.wikipedia.org/wiki/Don't_repeat_yourself
-[2]: 4-authentication-permissions-and-throttling.md
+[dry]: http://en.wikipedia.org/wiki/Don't_repeat_yourself
+[tut-4]: 4-authentication-permissions-and-throttling.md