django-rest-framework之基于類的視圖
前言:上一篇博客中,主要講的是請求和響應,項目里面views.py中的視圖函數都是基于函數的,并且我們介紹了@api_view這個很有用的裝飾器。同時,我們還介紹了APIView這個類,但是還沒使用它。在這篇文章中,我們要做的是把基于方法的視圖改為基于類的視圖,這是很強大的模式,使我們可以重用常用功能,可以減少代碼量。
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
List all snippets, or create a new snippet.
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
到這里應該很容易理解,和原來的相比,可以發現基于類的視圖把各種不同的HTTP請求分離開變成單個的方法,而不是if...elif...這樣的結構,所以這樣處理起來很更加的高效。同樣的,把另一個視圖函數也進行修改:
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
That's looking good. Again, it's still pretty similar to the function based view right now.
We'll also need to refactor our urls.py slightly now that we're using class-based views.
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.SnippetList.as_view()),
url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
這樣就可以運行程序了,功能和之前的是一樣的。以上,我覺得根本一點點難度都沒有……
使用mixin
使用基于類的視圖的一個重大勝利是它允許我們輕松地構造可重復使用的行為。
到目前為止,我們使用的創建/檢索/更新/刪除操作對于我們創建的任何模型支持的API視圖將非常相似。這些常見的行為是在REST框架的mixin類中實現的。
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
新的視圖類中繼承了 generic.GenericAPIView、mixins.ListModelMixin和mixins.CreatteModelMixin,類的作用看字面意思就能懂啦,mixins類為我們提供了list()和create()方法,當然,使用這兩個函數需要先設置queryset和serializer_class,這點我們查看一下mixins的源碼就可以看出來了,比如list方法:
class ListModelMixin(object):
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
同理,修改一下另一個視圖類:
class SnippetDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
使用通用的視圖類
到這里,視圖代碼已經簡化了許多了,但是我要告訴你的是,還可以進一步簡化。。。在此,讓我們一起在心中默念:
人生苦短,我用Python
進一步簡化就是連mixins類都不用了,只使用generics就可以了,代碼如下:
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
Wow, that's pretty concise. We've gotten a huge amount for free, and our code looks like good, clean, idiomatic Django.
來張效果圖,效果與與之前并不區別,只能用類方法寫視圖,減少了不少代碼,逼格更高了:

出處:http://www.rzrgm.cn/0zcl
文章未標明轉載則為原創博客。歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利.
1.非系統的學習也是在浪費時間
2.做一個會欣賞美,懂藝術,會藝術的技術人

浙公網安備 33010602011771號