Welcome to my personal website: www.comingnext.cn
Objective
In the previous article, the main focus was on the request and the response, the view function in views.py is based on the function, and we introduced @api_view, a useful decorator. At the same time, we introduced the Apiview class, but we haven't used it yet. In this article, we're going to change the method-based view to a class-based view, and we'll get to the Apiview.
Change to class-based view
Refactor snippets/view.py:
fromSnippets.modelsImportSnippet fromSnippets.serializersImportSnippetserializer fromDjango.httpImportHttp404 fromRest_framework.viewsImportApiview fromRest_framework.responseImportResponse fromRest_frameworkImportStatusclasssnippetlist (apiview):"""List all existing snippet or create a new snippet""" defGet (self, request, format=None): Snippets=Snippet.objects.all () serializer= Snippetserializer (Snippets, many=True)returnResponse (serializer.data)defPost (self, request, format=None): Serializer= Snippetserializer (data=request.data)ifserializer.is_valid (): Serializer.save ()returnResponse (Serializer.data, status=status. http_201_created)returnResponse (Serializer.errors, Status=status. Http_400_bad_request)
It should be easy to understand that, compared with the original, the class-based view can be found to separate various HTTP requests into a single method, rather than if...elif ... Such a structure, so it is more efficient to handle.
Similarly, the other view function is also modified:
classSnippetdetail (apiview):"""Retrieve view, update, or delete a snippet""" defGet_object (Self, PK):Try: returnSnippet.objects.get (pk=PK)exceptsnippet.doesnotexist:RaiseHttp404defGet (self, request, PK, format=None): Snippet=Self.get_object (PK) Serializer=Snippetserializer (snippet)returnResponse (serializer.data)defPut (self, request, PK, format=None): Snippet=Self.get_object (PK) Serializer= Snippetserializer (Snippet, data=request.data)ifserializer.is_valid (): Serializer.save ()returnResponse (serializer.data)returnResponse (Serializer.errors, status=status. Http_400_bad_request)defDelete (self, request, PK, format=None): Snippet=self.get_object (PK) snippet.delete ()returnResponse (Status=status. Http_204_no_content)
After changing to the class-based view, of course, you have to modify the route, the snippets/urls.py slightly modified:
from Import URL from Import Format_suffix_patterns from Import = [ url (r'^snippets/$', views. Snippetlist.as_view ()), URL (r'^snippets/(? p<pk>[0-9]+)/$'= format_suffix_patterns (urlpatterns)
So you can run the program, and the function is the same as before
Using the Mixins class
What are the benefits of using class-based views apart from the various HTTP requests that are mentioned above? The answer is yes-one of the biggest advantages of using class-based views is that it makes it easy to make reusable behavior.
Reusable behavior? Simply put, let's write down a little bit of similar code, so we'll introduce the Mixins class, which helps us encapsulate a lot of operations, simplify the code, use it very simply, edit the snippets/view.py function:
fromSnippets.modelsImportSnippet fromSnippets.serializersImportSnippetserializer fromRest_frameworkImportmixins fromRest_frameworkImportgenericsclasssnippetlist (mixins. Listmodelmixin, Mixins. Createmodelmixin, generics. Genericapiview): Queryset=Snippet.objects.all () Serializer_class=SnippetserializerdefGet (self, request, *args, * *Kwargs):returnSelf.list (Request, *args, * *Kwargs)defPost (self, request, *args, * *Kwargs):returnSelf.create (Request, *args, **kwargs)
The new view class inherits the generic. Genericapiview, Mixins. Listmodelmixin and Mixins.creattemodelmixin, the role of the class to see the literal meaning can understand, mixins class for us to provide a list () and create () method, of course, The use of these two functions need to set Queryset and Serializer_class, which we look at the Mixins source code can be seen, such as the list method:
classListmodelmixin (object):"""List a queryset. """ defList (self, request, *args, * *Kwargs): Queryset=Self.filter_queryset (Self.get_queryset ()) page=Self.paginate_queryset (Queryset)ifPage is notNone:serializer= Self.get_serializer (page, many=True)returnSelf.get_paginated_response (serializer.data) Serializer= Self.get_serializer (Queryset, many=True)returnResponse (Serializer.data)
The code here will get the query set and the serializer, respectively, through Get_queryset () and Get_serializer (), as well as other encapsulated methods.
Once you know this, it's easy to change another view class:
classSnippetdetail (mixins. Retrievemodelmixin, Mixins. Updatemodelmixin, Mixins. Destroymodelmixin, generics. Genericapiview): Queryset=Snippet.objects.all () Serializer_class=SnippetserializerdefGet (self, request, *args, * *Kwargs):returnSelf.retrieve (Request, *args, * *Kwargs)defPut (self, request, *args, * *Kwargs):returnSelf.update (Request, *args, * *Kwargs)defDelete (self, request, *args, * *Kwargs):returnSelf.destroy (Request, *args, **kwargs)
Using a common view class
Here, the view code has been simplified a lot, but what I want to tell you is that it can be further simplified ... Here, let us meditate in our hearts:
Life is short, I use Python
Further simplification is even the Mixins class is not used, only the use of generics can be, the code is as follows:
from Import Snippet from Import Snippetserializer from Import generics class snippetlist (generics. Listcreateapiview): = Snippet.objects.all () = Snippetserializerclass Snippetdetail (generics. Retrieveupdatedestroyapiview): = Snippet.objects.all () = Snippetserializer
Well, now the code is very concise, but short but lean, still can achieve the original function, random display:
Changing a function-based view to a class-based view is here, and the next article describes authorization and permissions ~
Django Write restful API (iii): Class-based view