通用視圖
drf 基于類的視圖允許我們編寫可重復(fù)使用的模式,并且提供了大量常用視圖及其常用模式,運用各類常用視圖可以快速構(gòu)建緊密映射到數(shù)據(jù)庫的 API 視圖,而如果視圖不符合我們的需求,可以繼承于常規(guī)的 APIView 類,自行擴展。
在使用通用試圖時,我們需要設(shè)置幾個屬性,如下:
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
若我們想要重寫視圖類的各種方法,可以如下:
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
def list(self, request):
# 注意使用`get_queryset()`而不是`self.queryset`
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
甚至,可以通過 .as_view() 方法傳遞類屬性,這樣連視圖類都不用寫了
url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
GenericAPIView
GenericAPIView 類繼承于APIView類,添加了常見行為
內(nèi)置的每一個通用試圖都是通過將GenericAPIView 類和一個或多個 minxin 類相互結(jié)合來構(gòu)建的
基本設(shè)置
如上所述,我們需要在視圖類中添加屬性控制視圖的行為:
-
queryset,從此視圖返回對象的查詢集。通常必須設(shè)置此屬性,或者通過調(diào)用get_queryset()方法覆蓋 -
serializer_class,用于驗證和反序列化輸入以及序列化輸出的序列化類。通常必須設(shè)置,或者調(diào)用get_serializer_class()方法覆蓋 -
lookup_field,用于執(zhí)行各個模型實例的對象查找的模型字段。默認為'pk' -
lookup_url_kwarg,用于對象查找的 URL 關(guān)鍵字參數(shù)。URL conf 應(yīng)該包含與此值相對應(yīng)的關(guān)鍵字參數(shù)。如果未設(shè)置,則默認使用與lookup_field相同的值
分頁
pagination_class 對列表進行分頁時使用的分頁類。默認值與DEFAULT_PAGINATION_CLASS設(shè)置相同,設(shè)置pagination_class = None將禁用此視圖的分頁
過濾
filter_backends 用于過濾查詢集的過濾器類的列表。默認值與DEFAULT_FILTER_CLASS設(shè)置相同
方法
get_queryset(self)
返回列表視圖的查詢集,并應(yīng)該將其用作查看詳細視圖的基礎(chǔ)。默認返回由 queryset 屬性指定的查詢集
應(yīng)該始終使用此方法, 而不是直接訪問 self.queryset,因為 REST 會在內(nèi)部對 self.queryset 的結(jié)果進行緩存用于后續(xù)所有請求
get_object(self)
返回詳細視圖的對象實例。默認使用lookup_field參數(shù)來過濾基本查詢集
可以覆蓋重寫以提供更復(fù)雜的行為,例如基于多個 URL kwarg 的對象查找,如:
def get_object(self):
queryset=self.get_queryset()
filter={}
for field in self.multiple_lookup_fields:
filter[field]=self.kwargs[field]
obj=get_object_or_404(queryset,**filter)
self.check_object_permissions(self.request,obj)
return obj
filter_queryset(self,queryset)
給定一個查詢集,使用過濾器進行過濾,返回一個新的查詢集,如下:
def filter_queryset(self,queryset):
filter_backends=(CategoryFilter,)
if 'geo_route' in self.request.query_params:
filter_backends=(GeoRouteFilter,CategoryFilter)
elif 'geo_point' in self.request.query_params:
filter_backends=(GeoPointFilter,CategoryFilter)
for backend in list(filter_backends):
queryset=backend.filter_queryset(self.request,queryset,view=self)
return queryset
get_serializer_class(self)
返回用以序列化的類,默認返回serializer_class屬性
可以覆蓋重寫以提供動態(tài)行為,例如使用不同的序列化器進行讀寫操作,或為不同類型的用戶提供不同的序列化器
例子:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
保存和刪除鉤子
以下方法由 mixin 類提供,可以很輕松地重寫對象的保存和刪除行為
-
perform_create(self,serializer),保存新對象實例時由CreateModelMixin調(diào)用 -
perform_update(self,serializer),保存現(xiàn)有對象實例時由UpdateModelMixin調(diào)用 -
perform_destroy(self,serializer),刪除對象實例時由DestroyModelMixin調(diào)用
這些鉤子對設(shè)置請求中隱含的但不屬于請求數(shù)據(jù)的屬性特別有用。例如,可以根據(jù)請求用戶或基于 URL 關(guān)鍵字參數(shù)在對象上設(shè)置屬性
def perform_create(self,serializer):
serializer.save(user=self.request.user)
這些鉤子的覆蓋對于添加保存對象之前或之后發(fā)生的行為(如發(fā)送確認電子郵件或記錄更新)也特別有用
def perform_create(self,serializer):
queryset=SignRequest.object.filter(user=self.request.user):
if queryset.exists():
raise ValidationError('You have already signed up')
serializer.save(user=self.request.user)
Mixins
mixins 類用于提供基本視圖行為的操作。mixin類提供操作方法,而不是直接定義處理方法,通過rest_framework.mixins導(dǎo)入
ListModelMixin
提供一個.list(request,*args,**kwargs)方法,實現(xiàn)列出一個查詢集
如果查詢集已填充,則返回200 OK響應(yīng),并將 queryset 的序列化表示形式作為響應(yīng)的主體
CreateModelMixin
提供.create(request,*arg,**kwargs)方法,實現(xiàn)創(chuàng)建和保存新模型數(shù)據(jù)實例
如果創(chuàng)建了一個對象,則會返回一個201 Created響應(yīng),并將該對象的序列化表示形式作為響應(yīng)的主體
如果為創(chuàng)建對象提供的請求數(shù)據(jù)無效,則將返回400 Bad Request響應(yīng),并將錯誤細節(jié)作為響應(yīng)的主體
RetrieveModelMixin
提供.retrieve(request,*args,**kwargs)方法,該方法實現(xiàn)在響應(yīng)中返回現(xiàn)有的模型實例
如果可以獲取對象,則返回200 OK響應(yīng),并將對象的序列化表示為響應(yīng)的主體。否則,將返回一個404 Not Found
UpdateModelMixin
提供.update(request,*args,**kwargs)方法,實現(xiàn)更新和保存現(xiàn)有模型實例。還提供了一個 .partial_update(request, *args, **kwargs) 方法,它與更新方法類似,只是更新的所有字段都是可選的。這允許支持 HTTP PATCH 請求。
如果成功更新對象,則返回 200 OK 響應(yīng),并將對象的序列化表示形式作為響應(yīng)的主體
如果提供的用于更新對象的請求數(shù)據(jù)無效,則將返回 400 Bad Request 響應(yīng),并將錯誤細節(jié)作為響應(yīng)的主體
DestroyModelMixin
提供一個 .destroy(request, *args, **kwargs) 方法,實現(xiàn)現(xiàn)有模型實例的刪除
如果一個對象被刪除,則返回一個 204 No Content ,否則它將返回一個 404 Not Found
內(nèi)置視圖類
以下類是具體的通用試圖,從rest_framework.generics導(dǎo)入
CreateAPIView
僅用于創(chuàng)建實例,提供一個post請求的處理方法
繼承自:GenericAPIView,CreateModelMixin
ListAPIView
僅用于讀取模型實例列表,提供一個get請求的處理方法
繼承自:GenericAPIView,ListModelMixin
RetrieveAPIView
僅用于查詢單個模型實例,提供一個get請求的處理方法
繼承自:GenericAPIView,RetrieveModelMixin
DestroyAPIView
僅用于刪除單個模型實例,提供一個delete請求的處理方法
繼承其:GenericAPIView, DestroyModelMixin
UpdateAPIView
僅用于更新單個模型實例,提供 put 和 patch 請求的處理方法
繼承自: GenericAPIView, UpdateModelMixin
ListCreateAPIView
既可以獲取也可以實例集合,也可以創(chuàng)建實例列表,提供 get 和 post 請求的處理方法
繼承自: GenericAPIView, ListModelMixin,CreateModelMixin
RetrieveUpdateAPIView
既可以查詢也可以更新單個實例,提供 get,put 和 patch 請求的處理方法
繼承自: GenericAPIView, RetrieveModelMixin,UpdateModelMixin
RetrieveDestroyAPIView
既可以查詢也可以刪除單個實例,提供 get 和 delete 請求的處理方法
繼承自: GenericAPIView, RetrieveModelMixin,DestroyModelMixin
RetrieveUpdateDestroyAPIView
同時支持查詢,更新,刪除,提供 get,put,patch 和 delete 請求的處理方法
繼承自: GenericAPIView, RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin