基于類的視圖的一個主要優(yōu)點(diǎn)是它們允許你組合可重復(fù)使用的行為。 REST框架通過提供大量預(yù)構(gòu)建視圖來提供常用模式,從而充分利用了這一點(diǎn)。
REST框架提供的通用視圖允許您快速構(gòu)建緊密映射到數(shù)據(jù)庫模型的API視圖。
如果通用視圖不適合您的API需求,則可以下拉使用常規(guī)APIView類,或者重用通用視圖使用的mixins和基類來組成自己的可重用通用視圖集。
示例
通常,在使用通用視圖時,您將覆蓋該視圖,并設(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,)
對于更復(fù)雜的情況,您可能還想覆蓋視圖類中的各種方法。例如。
class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)
def list(self, request):
# Note the use of `get_queryset()` instead of `self.queryset`
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
對于非常簡單的情況,您可能希望使用.as_view()方法傳遞任何類屬性。例如,您的URLconf可能包含以下條目:
url(r'^/users/', ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
API參考
GenericAPIView
此類擴(kuò)展了REST框架的APIView類,為標(biāo)準(zhǔn)列表和詳細(xì)信息視圖添加了常用的行為。
提供的每個具體通用視圖都是通過將GenericAPIView與一個或多個mixin類組合而構(gòu)建的。
屬性
基本設(shè)置:
以下屬性控制基本視圖行為。
- queryset - 應(yīng)該用于從此視圖返回對象的查詢集. 通常,您必須設(shè)置此屬性,或覆蓋get_queryset()方法。如果要覆蓋視圖方法,則必須調(diào)用get_queryset()而不是直接訪問此屬性,因?yàn)閝ueryset將被評估一次,并且將為所有后續(xù)請求緩存這些結(jié)果。
- serializer_class - 應(yīng)該用于驗(yàn)證和反序列化輸入以及序列化輸出的序列化程序類。 通常,您必須設(shè)置此屬性,或覆蓋get_serializer_class()方法。
- lookup_field - 應(yīng)該用于執(zhí)行單個模型實(shí)例的對象查找的模型字段。 默認(rèn)為'pk'。 請注意,使用超鏈接API時,如果需要使用自定義值,則需要確保API視圖和序列化程序類都設(shè)置查找字段。
- lookup_url_kwarg - 應(yīng)該用于對象查找的URL關(guān)鍵字參數(shù)。 URL conf應(yīng)包含與此值對應(yīng)的關(guān)鍵字參數(shù)。 如果未設(shè)置,則默認(rèn)使用與lookup_field相同的值。
分頁:
與列表視圖一起使用時,以下屬性用于控制分頁。
- pagination_clas - 分頁列表結(jié)果時應(yīng)使用的分頁類。 默認(rèn)為與DEFAULT_PAGINATION_CLASS設(shè)置相同的值,即'rest_framework.pagination.PageNumberPagination'。 設(shè)置pagination_class = None將禁用此視圖上的分頁。
過濾:
- filter_backends - 應(yīng)該用于過濾查詢集的過濾器后端類列表。默認(rèn)值與DEFAULT_FILTER_BACKENDS設(shè)置的值相同。
Methods
Base methods:
get_queryset(self)
返回應(yīng)該用于列表視圖的查詢集,該查詢集應(yīng)該用作詳細(xì)視圖中查找的基礎(chǔ)。默認(rèn)返回queryset屬性指定的查詢集。
應(yīng)始終使用此方法而不是直接訪問self.queryset,因?yàn)閟elf.queryset僅被評估一次,并且這些結(jié)果將被緩存用于所有后續(xù)請求。
可以重寫以提供動態(tài)行為,例如返回查詢集,該查詢集特定于發(fā)出請求的用戶。
例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
get_object(self)
返回應(yīng)該用于詳細(xì)視圖的對象實(shí)例。 默認(rèn)使用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
請注意,如果您的API不包含任何對象級別權(quán)限,您可以選擇性地排除self.check_object_permissions,并簡單地從get_object_or_404查找返回該對象。
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)
返回應(yīng)該用于序列化程序的類。 默認(rèn)返回serializer_class屬性。
可以重寫以提供動態(tài)行為,例如使用不同的序列化程序進(jìn)行讀寫操作,或者為不同類型的用戶提供不同的序列化程序。
例如:
def get_serializer_class(self):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
Save and deletion hooks:
mixin類提供了以下方法,并提供了對象保存或刪除行為的輕松覆蓋。
- perform_create(self, serializer) - 在保存新對象實(shí)例時由CreateModelMixin調(diào)用。
- perform_update(self, serializer) - 在保存現(xiàn)有對象實(shí)例時由UpdateModelMixin調(diào)用。
- perform_destroy(self, instance) - 在刪除對象實(shí)例時由DestroyModelMixin調(diào)用。
這些鉤子對于設(shè)置請求中隱含的屬性特別有用,但不是請求數(shù)據(jù)的一部分。例如,您可以根據(jù)請求用戶或基于URL關(guān)鍵字參數(shù)在對象上設(shè)置屬性。
def perform_create(self, serializer):
serializer.save(user=self.request.user)
這些覆蓋點(diǎn)對于添加在保存對象之前或之后發(fā)生的行為(例如通過電子郵件發(fā)送確認(rèn)或記錄更新)也特別有用。
def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
您還可以通過引發(fā)ValidationError()來使用這些鉤子來提供額外的驗(yàn)證。如果您需要在數(shù)據(jù)庫保存點(diǎn)應(yīng)用某些驗(yàn)證邏輯,這可能很有用。例如:
def perform_create(self, serializer):
queryset = SignupRequest.objects.filter(user=self.request.user)
if queryset.exists():
raise ValidationError('You have already signed up')
serializer.save(user=self.request.user)
注意:這些方法替換了舊版本的2.x pre_save,post_save,pre_delete和post_delete方法,這些方法不再可用。
其他方法:
您通常不需要覆蓋以下方法,但如果您使用GenericAPIView編寫自定義視圖,則可能需要調(diào)用它們。
-
get_serializer_context(self)- 返回一個字典,其中包含應(yīng)提供給序列化程序的任何額外上下文。 默認(rèn)包括“請求”,“查看”和“格式”鍵。 -
get_serializer(self,instance = None,data = None,many = False,partial = False)- 返回一個序列化程序?qū)嵗?/li> -
get_paginated_response(self,data)- 返回分頁樣式的Response對象。 -
paginate_queryset(self,queryset)- 如果需要,可以返回一個查詢集,返回頁面對象;如果沒有為此視圖配置分頁,則為“無”。 -
filter_queryset(self,queryset)- 給定一個查詢集,使用正在使用的過濾后端進(jìn)行過濾,返回一個新的查詢集。
Mixins
mixin類提供用于提供基本視圖行為的操作。 請注意,mixin類提供了操作方法,而不是直接定義處理程序方法,例如.get()和.post()。 這允許更靈活的行為組合。
mixin類可以從rest_framework.mixins導(dǎo)入。
ListModelMixin
提供.list(request,* args,** kwargs)方法,用于實(shí)現(xiàn)列出查詢集。
如果填充了查詢集,則返回200 OK響應(yīng),并將查詢集的序列化表示作為響應(yīng)的主體。 可選地,可以對響應(yīng)數(shù)據(jù)進(jìn)行分頁。
CreateModelMixin
提供.create(request,* args,** kwargs)方法,用于實(shí)現(xiàn)創(chuàng)建和保存新模型實(shí)例。
如果創(chuàng)建了一個對象,則返回201 Created響應(yīng),該對象的序列化表示形式為響應(yīng)的主體。 如果表示包含名為url的鍵,則響應(yīng)的Location標(biāo)頭將填充該值。
如果為創(chuàng)建對象而提供的請求數(shù)據(jù)無效,則將返回400 Bad Request響應(yīng),并將錯誤詳細(xì)信息作為響應(yīng)的主體。
RetrieveModelMixin
提供.retrieve(request,* args,** kwargs)方法,該方法實(shí)現(xiàn)在響應(yīng)中返回現(xiàn)有模型實(shí)例。
如果可以檢索對象,則返回200 OK響應(yīng),并將對象的序列化表示作為響應(yīng)的主體。 否則它將返回404 Not Found。
UpdateModelMixin
提供.update(request,* args,** kwargs)方法,用于實(shí)現(xiàn)更新和保存現(xiàn)有模型實(shí)例。
還提供了.partial_update(request,* args,** kwargs)方法,該方法與update方法類似,不同之處在于更新的所有字段都是可選的。 這允許支持HTTP PATCH請求。
如果對象被更新,則返回200 OK響應(yīng),并將對象的序列化表示作為響應(yīng)的主體。
如果為更新對象而提供的請求數(shù)據(jù)無效,則將返回400 Bad Request響應(yīng),并將錯誤詳細(xì)信息作為響應(yīng)的主體。
DestroyModelMixin
提供.destroy(request,* args,** kwargs)方法,用于實(shí)現(xiàn)對現(xiàn)有模型實(shí)例的刪除。
如果刪除了一個對象,則返回204 No Content響應(yīng),否則返回404 Not Found。
Concrete View Classes
以下類是具體的通用視圖。如果您使用的是通用視圖,這通常是您將要工作的級別,除非您需要大量自定義的行為。
可以從rest_framework.generics導(dǎo)入視圖類。
CreateAPIView
用于僅創(chuàng)建端點(diǎn)。
提供post方法處理程序。
擴(kuò)展:GenericAPIView,CreateModelMixin
ListAPIView
用于只讀端點(diǎn)以表示模型實(shí)例的集合。
提供get方法處理程序。
擴(kuò)展:GenericAPIView,ListModelMixin
RetrieveAPIView
用于表示單個模型實(shí)例的只讀端點(diǎn)。
提供get方法處理程序。
擴(kuò)展:GenericAPIView,RetrieveModelMixin
DestroyAPIView
用于單個模型實(shí)例的僅刪除端點(diǎn)。
提供刪除方法處理程序。
擴(kuò)展:GenericAPIView,DestroyModelMixin
UpdateAPIView
用于單個模型實(shí)例的僅更新端點(diǎn)。
提供put和patch方法處理程序。
擴(kuò)展:GenericAPIView,UpdateModelMixin
ListCreateAPIView
用于讀寫端點(diǎn)以表示模型實(shí)例的集合。
提供get和post方法處理程序。
擴(kuò)展:GenericAPIView,ListModelMixin,CreateModelMixin
RetrieveUpdateAPIView
用于讀取或更新端點(diǎn)以表示單個模型實(shí)例。
提供get,put和patch方法處理程序。
擴(kuò)展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin
RetrieveDestroyAPIView
用于讀取或刪除端點(diǎn)以表示單個模型實(shí)例。
提供get和delete方法處理程序。
擴(kuò)展:GenericAPIView,RetrieveModelMixin,DestroyModelMixin
RetrieveUpdateDestroyAPIView
用于讀寫 - 刪除端點(diǎn)以表示單個模型實(shí)例。
提供get,put,patch和delete方法處理程序。
擴(kuò)展:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin
Customizing the generic views
通常,您會希望使用現(xiàn)有的通用視圖,但使用一些略微自定義的行為。 如果您發(fā)現(xiàn)自己在多個位置重復(fù)使用某些自定義行為,則可能需要將該行為重構(gòu)為公共類,然后您可以根據(jù)需要將其應(yīng)用于任何視圖或視圖集。
Creating custom mixins
例如,如果您需要根據(jù)URL conf中的多個字段查找對象,則可以創(chuàng)建如下所示的mixin類:
class MultipleFieldLookupMixin(object):
"""
Apply this mixin to any view or viewset to get multiple field filtering
based on a `lookup_fields` attribute, instead of the default single field filtering.
"""
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
filter = {}
for field in self.lookup_fields:
if self.kwargs[field]: # Ignore empty fields.
filter[field] = self.kwargs[field]
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
然后,只要您需要應(yīng)用自定義行為,就可以將此mixin簡單地應(yīng)用于視圖或視圖集。
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ('account', 'username')
如果您需要使用自定義行為,則使用自定義mixins是一個不錯的選擇。
Creating custom base classes
如果您在多個視圖中使用mixin,則可以更進(jìn)一步,創(chuàng)建自己的一組基本視圖,然后可以在整個項(xiàng)目中使用。例如:
class BaseRetrieveView(MultipleFieldLookupMixin,
generics.RetrieveAPIView):
pass
class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
generics.RetrieveUpdateDestroyAPIView):
pass
如果您的自定義行為始終需要在整個項(xiàng)目中的大量視圖中重復(fù),那么使用自定義基類是一個不錯的選擇。
PUT as create
在3.0版之前,REST框架將處理后的PUT混合為更新或創(chuàng)建操作,具體取決于對象是否已存在。
允許PUT作為創(chuàng)建操作是有問題的,因?yàn)樗厝槐┞队嘘P(guān)對象存在或不存在的信息。 透明地允許重新創(chuàng)建先前刪除的實(shí)例也不一定比僅返回404響應(yīng)更好的默認(rèn)行為。
兩種樣式“PUT as 404”和“PUT as create”在不同情況下都可以有效,但從版本3.0開始,我們現(xiàn)在使用404行為作為默認(rèn)值,因?yàn)樗唵?,更明顯。
如果您需要通用的PUT-as-create行為,您可能希望將類似此類的AllowPUTAsCreateMixin類作為mixin包含在您的視圖中。
Third party packages
以下第三方包提供了其他通用視圖實(shí)現(xiàn)。
Django REST Framework bulk
django-rest-framework-bulk包實(shí)現(xiàn)了通用視圖mixins以及一些常見的具體通用視圖,以允許通過API請求應(yīng)用批量操作。
Django Rest Multiple Models
Django Rest Multiple Models提供了一個通用視圖(和mixin),用于通過單個API請求發(fā)送多個序列化模型和/或查詢集。