Tweak tutorial slightly

This commit is contained in:
Tom Christie 2012-09-07 09:45:23 +01:00
parent 07fe60772c
commit 57e9a36c3a
2 changed files with 28 additions and 18 deletions

View File

@ -126,7 +126,7 @@ margin-top: 5px;
<div class="span3"> <div class="span3">
<div class="well affix span3"> <div class="well affix span3">
<ul class="nav nav-list side-nav"> <ul class="nav nav-list side-nav">
<li class="main"><a href="#tutorial-2-request-and-response-objects">Tutorial 2: Request and Response objects</a></li> <li class="main"><a href="#tutorial-2-requests-and-responses">Tutorial 2: Requests and Responses</a></li>
<li><a href="#request-objects">Request objects</a></li> <li><a href="#request-objects">Request objects</a></li>
<li><a href="#response-objects">Response objects</a></li> <li><a href="#response-objects">Response objects</a></li>
<li><a href="#status-codes">Status codes</a></li> <li><a href="#status-codes">Status codes</a></li>
@ -141,7 +141,7 @@ margin-top: 5px;
</div> </div>
<div class="span9"> <div class="span9">
<h1 id="tutorial-2-request-and-response-objects">Tutorial 2: Request and Response objects</h1> <h1 id="tutorial-2-requests-and-responses">Tutorial 2: Requests and Responses</h1>
<p>From this point we're going to really start covering the core of REST framework. <p>From this point we're going to really start covering the core of REST framework.
Let's introduce a couple of essential building blocks.</p> Let's introduce a couple of essential building blocks.</p>
<h2 id="request-objects">Request objects</h2> <h2 id="request-objects">Request objects</h2>

View File

@ -126,17 +126,17 @@ margin-top: 5px;
<div class="span3"> <div class="span3">
<div class="well affix span3"> <div class="well affix span3">
<ul class="nav nav-list side-nav"> <ul class="nav nav-list side-nav">
<li class="main"><a href="#tutorial-3-using-class-based-views">Tutorial 3: Using Class Based Views</a></li> <li class="main"><a href="#tutorial-3-class-based-views">Tutorial 3: Class Based Views</a></li>
<li><a href="#rewriting-our-api-using-class-based-views">Rewriting our API using class based views</a></li> <li><a href="#rewriting-our-api-using-class-based-views">Rewriting our API using class based views</a></li>
<li><a href="#using-mixins">Using mixins</a></li> <li><a href="#using-mixins">Using mixins</a></li>
<li><a href="#reusing-generic-class-based-views">Reusing generic class based views</a></li> <li><a href="#using-generic-class-based-views">Using generic class based views</a></li>
</ul> </ul>
</div> </div>
</div> </div>
<div class="span9"> <div class="span9">
<h1 id="tutorial-3-using-class-based-views">Tutorial 3: Using Class Based Views</h1> <h1 id="tutorial-3-class-based-views">Tutorial 3: Class Based Views</h1>
<p>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 <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</p> <p>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 <a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself">DRY</a>.</p>
<h2 id="rewriting-our-api-using-class-based-views">Rewriting our API using class based views</h2> <h2 id="rewriting-our-api-using-class-based-views">Rewriting our API using class based views</h2>
<p>We'll start by rewriting the root view as a class based view. All this involves is a little bit of refactoring.</p> <p>We'll start by rewriting the root view as a class based view. All this involves is a little bit of refactoring.</p>
@ -203,16 +203,16 @@ class CommentRoot(APIView):
Okay, we're done. If you run the development server everything should be working just as before.</p> Okay, we're done. If you run the development server everything should be working just as before.</p>
<h2 id="using-mixins">Using mixins</h2> <h2 id="using-mixins">Using mixins</h2>
<p>One of the big wins of using class based views is that it allows us to easily compose reusable bits of behaviour.</p> <p>One of the big wins of using class based views is that it allows us to easily compose reusable bits of behaviour.</p>
<p>The create/retrieve/update/delete operations that we've been using so far is going to be pretty simliar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.</p> <p>The create/retrieve/update/delete operations that we've been using so far are going to be pretty simliar for any model-backed API views we create. Those bits of common behaviour are implemented in REST framework's mixin classes.</p>
<p>We can compose those mixin classes, to recreate our existing API behaviour with less code.</p> <p>Let's take a look at how we can compose our views by using the mixin classes.</p>
<pre><code>from blog.models import Comment <pre><code>from blog.models import Comment
from blog.serializers import CommentSerializer from blog.serializers import CommentSerializer
from djangorestframework import mixins from djangorestframework import mixins
from djangorestframework import views from djangorestframework import generics
class CommentRoot(mixins.ListModelMixin, class CommentRoot(mixins.ListModelMixin,
mixins.CreateModelMixin, mixins.CreateModelMixin,
views.MultipleObjectBaseView): generics.MultipleObjectBaseView):
model = Comment model = Comment
serializer_class = CommentSerializer serializer_class = CommentSerializer
@ -222,10 +222,14 @@ class CommentRoot(mixins.ListModelMixin,
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) return self.create(request, *args, **kwargs)
class CommentInstance(mixins.RetrieveModelMixin, comment_root = CommentRoot.as_view()
</code></pre>
<p>We'll take a moment to examine exactly what's happening here - We're building our view using <code>MultipleObjectBaseView</code>, and adding in <code>ListModelMixin</code> and <code>CreateModelMixin</code>.</p>
<p>The base class provides the core functionality, and the mixin classes provide the <code>.list()</code> and <code>.create()</code> actions. We're then explictly binding the <code>get</code> and <code>post</code> methods to the appropriate actions. Simple enough stuff so far.</p>
<pre><code>class CommentInstance(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin, mixins.UpdateModelMixin,
mixins.DestroyModelMixin, mixins.DestroyModelMixin,
views.SingleObjectBaseView): generics.SingleObjectBaseView):
model = Comment model = Comment
serializer_class = CommentSerializer serializer_class = CommentSerializer
@ -237,23 +241,29 @@ class CommentInstance(mixins.RetrieveModelMixin,
def delete(self, request, *args, **kwargs): def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) return self.destroy(request, *args, **kwargs)
comment_instance = CommentInstance.as_view()
</code></pre> </code></pre>
<h2 id="reusing-generic-class-based-views">Reusing generic class based views</h2> <p>Pretty similar. This time we're using the <code>SingleObjectBaseView</code> class to provide the core functionality, and adding in mixins to provide the <code>.retrieve()</code>, <code>.update()</code> and <code>.destroy()</code> actions.</p>
<p>That's a lot less code than before, but we can go one step further still. REST framework also provides a set of already mixed-in views.</p> <h2 id="using-generic-class-based-views">Using generic class based views</h2>
<p>Using the mixin classes we've rewritten the views to use slightly less code than before, but we can go one step further. REST framework provides a set of already mixed-in generic views that we can use.</p>
<pre><code>from blog.models import Comment <pre><code>from blog.models import Comment
from blog.serializers import CommentSerializer from blog.serializers import CommentSerializer
from djangorestframework import views from djangorestframework import generics
class CommentRoot(views.RootModelView): class CommentRoot(generics.RootAPIView):
model = Comment model = Comment
serializer_class = CommentSerializer serializer_class = CommentSerializer
class CommentInstance(views.InstanceModelView): comment_root = CommentRoot.as_view()
class CommentInstance(generics.InstanceAPIView):
model = Comment model = Comment
serializer_class = CommentSerializer serializer_class = CommentSerializer
comment_instance = CommentInstance.as_view()
</code></pre> </code></pre>
<p>Wow, that's pretty concise. We've got a huge amount for free, and our code looks like <p>Wow, that's pretty concise. We've got a huge amount for free, and our code looks like good, clean, idomatic Django.</p>
good, clean, idomatic Django.</p>
<p>Next we'll move onto <a href="4-authentication-permissions-and-throttling">part 4 of the tutorial</a>, 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.</p> <p>Next we'll move onto <a href="4-authentication-permissions-and-throttling">part 4 of the tutorial</a>, 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.</p>
</div><!--/span--> </div><!--/span-->
</div><!--/row--> </div><!--/row-->