Django的標(biāo)準(zhǔn) views...是為更快捷地使用常見的使用模式而開發(fā)的... 它們采用在view開發(fā)中找到的某些常見語(yǔ)法和模式,并對(duì)它們進(jìn)行抽象,以便你可以快速寫出數(shù)據(jù)的常見視圖,而無(wú)需重復(fù)自己?!?nbsp;Django 文檔
基于類的視圖的主要優(yōu)點(diǎn)之一是它們?cè)试S你組合一些可重用的行為。 REST framework通過(guò)提供許多預(yù)先構(gòu)建的視圖來(lái)提供常用的模式來(lái)利用這一優(yōu)點(diǎn)。
REST framework 提供的通用視圖允許您快速構(gòu)建與數(shù)據(jù)庫(kù)模型密切映射的API視圖。
如果通用視圖不適合你的API的需求,你可以選擇使用常規(guī) APIView 類,或重用通用視圖使用的mixins和基類來(lái)組成你自己的一組可重用的通用視圖。
通常在使用通用視圖時(shí),你將覆蓋視圖,并設(shè)置多個(gè)類屬性。
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, )
對(duì)于更復(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)
對(duì)于非常簡(jiǎn)單的情況,你可能想使用 .as_view() 方法傳遞任何類屬性。 比如:你的URLconf可能包括類似以下條目:
url(r'^/users/', ListCreateAPIView.as_view\(queryset=User.objects.all(), serializer_class=UserSerializer), name='user-list')
此類擴(kuò)展了REST框架的 APIView 類,為標(biāo)準(zhǔn)list和detail view 添加了通常需要的行為。
提供的每個(gè)具體通用視圖是通過(guò)將 GenericAPIView 與一個(gè)或多個(gè)mixin類組合來(lái)構(gòu)建的。
基本設(shè)置:
以下屬性控制著基本視圖的行為。
Pagination:
以下屬性用于在與列表視圖一起使用時(shí)控制分頁(yè)。
Filtering:
Base methods:
返回列表視圖中實(shí)用的查詢集,該查詢集還用作詳細(xì)視圖中的查找基礎(chǔ)。默認(rèn)返回由 queryset 屬性指定的查詢集。 這個(gè)方法應(yīng)該總是被調(diào)用而不是直接訪問(wèn) self.queryset ,因?yàn)?nbsp;self.queryset 只會(huì)被計(jì)算一起,然后這些結(jié)果將為后續(xù)的請(qǐng)求緩存起來(lái)。 該方法可能會(huì)被重寫以提供動(dòng)態(tài)行為,比如返回基于發(fā)出請(qǐng)求的用戶的結(jié)果集。
例如:
def get_queryset(self):
user = self.request.user
return user.accounts.all()
返回應(yīng)用于詳細(xì)視圖的對(duì)象實(shí)例。默認(rèn)使用 lookup_field 參數(shù)過(guò)濾基本的查詢集。
該方法可以被重寫以提供更復(fù)雜的行為,例如基于多個(gè) URL 參數(shù)的對(duì)象查找。
例如:
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
請(qǐng)注意,如果你的API不包含任何對(duì)象級(jí)的權(quán)限控制,你可以選擇不執(zhí)行self.check_object_permissions,簡(jiǎn)單的返回 get_object_or_404 查找的對(duì)象即可。
給定一個(gè)queryset,使用任何過(guò)濾器后端進(jìn)行過(guò)濾,返回一個(gè)新的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
返回應(yīng)用于序列化的類。默認(rèn)為返回 serializer_class 屬性的值。
可以被重寫以提供動(dòng)態(tài)的行為,例如對(duì)于讀取和寫入操作使用不同的序列化器,或者為不同類型的用戶提供不同的序列化器。
例如:
def get_serializer_class(self\):
if self.request.user.is_staff:
return FullAccountSerializer
return BasicAccountSerializer
Save and deletion hooks:
以下方法由mixin類提供,并提供對(duì)象保存或刪除行為的簡(jiǎn)單重寫。
這些鉤子對(duì)于設(shè)置請(qǐng)求中隱含的但不是請(qǐng)求數(shù)據(jù)的一部分的屬性特別有用。例如,你可以根據(jù)請(qǐng)求用戶或基于URL關(guān)鍵字參數(shù)在對(duì)象上設(shè)置屬性。
def perform_create(self, serializer):
serializer.save(user=self.request.user)
這些可重寫的關(guān)鍵點(diǎn)對(duì)于添加在保存對(duì)象之前或之后發(fā)生的行為(例如通過(guò)電子郵件發(fā)送確認(rèn)或記錄更新日志)也特別有用。
def perform_update(self, serializer):
instance = serializer.save()
send_email_confirmation(user=self.request.user, modified=instance)
你還可以使用這些鉤子通過(guò)拋出 ValidationError() 來(lái)提供額外的驗(yàn)證。當(dāng)你需要在數(shù)據(jù)庫(kù)保存時(shí)應(yīng)用一些驗(yàn)證邏輯時(shí),這會(huì)很有用。 例如:
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 編寫自定義視圖的時(shí)候可能會(huì)調(diào)用它們。
Mixin 類提供用于提供基本視圖行為的操作。注意mixin類提供動(dòng)作方法,而不是直接定義處理程序方法,例如 .get() 和 .post(), 這允許更靈活的行為組成。
Mixin 類可以從 rest_framework.mixins導(dǎo)入。
提供一個(gè) .list(request, *args, **kwargs) 方法,實(shí)現(xiàn)列出結(jié)果集。
如果查詢集被填充了數(shù)據(jù),則返回 200 OK 響應(yīng),將查詢集的序列化表示作為響應(yīng)的主體。相應(yīng)數(shù)據(jù)可以任意分頁(yè)。
提供 .create(request, *args, **kwargs) 方法,實(shí)現(xiàn)創(chuàng)建和保存一個(gè)新的model實(shí)例。
如果創(chuàng)建了一個(gè)對(duì)象,這將返回一個(gè) 201 Created 響應(yīng),將該對(duì)象的序列化表示作為響應(yīng)的主體。如果序列化的表示中包含名為 url的鍵,則響應(yīng)的 Location 頭將填充該值。
如果為創(chuàng)建對(duì)象提供的請(qǐng)求數(shù)據(jù)無(wú)效,將返回 400 Bad Request,其中錯(cuò)誤詳細(xì)信息作為響應(yīng)的正文。
提供一個(gè) .retrieve(request, *args, **kwargs) 方法,實(shí)現(xiàn)返回響應(yīng)中現(xiàn)有模型的實(shí)例。
如果可以檢索對(duì)象,則返回 200 OK 響應(yīng),將該對(duì)象的序列化表示作為響應(yīng)的主體。否則將返回 404 Not Found。
提供 .update(request, *args, **kwargs) 方法,實(shí)現(xiàn)更新和保存現(xiàn)有模型實(shí)例。
同時(shí)還提供了一個(gè) .partial_update(request, *args, **kwargs) 方法,這個(gè)方法和 update 方法類似,但更新的所有字段都是可選的。這允許支持 HTTP PATCH 請(qǐng)求。
如果一個(gè)對(duì)象被更新,這將返回一個(gè) 200 OK 響應(yīng),將對(duì)象的序列化表示作為響應(yīng)的主體。
如果為更新對(duì)象提供的請(qǐng)求數(shù)據(jù)無(wú)效,將返回一個(gè) 400 Bad Request 響應(yīng),錯(cuò)誤詳細(xì)信息作為響應(yīng)的正文。
提供一個(gè) .destroy(request, *args, **kwargs) 方法,實(shí)現(xiàn)刪除現(xiàn)有模型實(shí)例。
如果刪除對(duì)象,則返回 204 No Content 響應(yīng),否則返回 404 Not Found。
以下類是具體的通用視圖。這通常是你真正用到的那些,除非你需要深度定制的行為。
這些視圖類可以從 rest_framework.generics導(dǎo)入。
用于 僅創(chuàng)建 端點(diǎn)。
提供一個(gè) post 方法處理程序。
擴(kuò)展: GenericAPIView, CreateModelMixin
用于 只讀 端點(diǎn)以表示模型實(shí)例集合 。
提供一個(gè) get 方法處理程序。
擴(kuò)展: GenericAPIView, ListModelMixin
用于只讀 端點(diǎn)以表示單個(gè)模型實(shí)例。
提供一個(gè) get 方法處理程序。
擴(kuò)展: GenericAPIView, RetrieveModelMixin
用于只刪除端點(diǎn)以表示單個(gè)模型實(shí)例。
提供一個(gè) delete 方法處理程序。
擴(kuò)展: GenericAPIView, DestroyModelMixin
用于只更新端點(diǎn)以表示單個(gè)模型實(shí)例。
提供一個(gè) put和patch方法處理程序。
擴(kuò)展: GenericAPIView, UpdateModelMixin
用于讀寫端點(diǎn)以表示模型實(shí)例的集合。
提供一個(gè) get 和 post 方法的處理程序。
擴(kuò)展: GenericAPIView, ListModelMixin, CreateModelMixin
用于 讀取或更新 端點(diǎn)以表示 單個(gè)模型實(shí)例。
提供 get, put 和 patch 方法的處理程序。
擴(kuò)展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin
用于 讀取或刪除 端點(diǎn)以表示 單個(gè)模型實(shí)例。
提供 get 和 delete 方法的處理程序。
擴(kuò)展: GenericAPIView, RetrieveModelMixin, DestroyModelMixin
用于 讀寫刪除 端點(diǎn)以表示 單個(gè)模型實(shí)例。
提供 get, put, patch 和 delete方法的處理程序。
擴(kuò)展: GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
通常你會(huì)想使用現(xiàn)有的通用視圖,但是使用一些簡(jiǎn)單的自定義的行為。如果你發(fā)現(xiàn)自己在多個(gè)地方重復(fù)使用了一些自定義行為,你可能想將行為重構(gòu)為一個(gè)公共類,然后只需根據(jù)需要應(yīng)用到任何視圖或視圖集。
例如,如果你需要基于 URL conf中的多個(gè)字段查找對(duì)象,則可以創(chuàng)建一個(gè)如下所示的 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() # 獲取基本的queryset
queryset = self.filter_queryset(queryset) # 應(yīng)用任何過(guò)濾器后端
filter = {}
for field in self.lookup_fields:
if self.kwargs[field]: # Ignore empty fields.
filter[field] = self.kwargs[field]
return get_object_or_404(queryset, **filter) # 查找對(duì)象
然后,你可以在需要應(yīng)用自定義行為時(shí)隨時(shí)將此mixin類應(yīng)用于視圖或視圖集。
class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
lookup_fields = ('account', 'username')
如果你需要使用自定義行為,那么使用自定義mixin是一個(gè)不錯(cuò)的選擇。
如果你在多個(gè)視圖中使用mixin,你可以進(jìn)一步創(chuàng)建你自己的一組基本視圖,然后可以在整個(gè)項(xiàng)目中使用。舉個(gè)例子:
class BaseRetrieveView(MultipleFieldLookupMixin,
generics.RetrieveAPIView):
pass
class BaseRetrieveUpdateDestroyView(MultipleFieldLookupMixin,
generics.RetrieveUpdateDestroyAPIView):
pass
如果你的自定義行為始終需要在整個(gè)項(xiàng)目中的大量視圖中重復(fù),則使用自定義基類是一個(gè)不錯(cuò)的選擇。
在3.0版本之前,REST framework mixins 將 PUT 視為更新或創(chuàng)建操作,具體取決于對(duì)象是否已存在。
允許 PUT 作為創(chuàng)建操作是有問(wèn)題的,因?yàn)樗厝粫?huì)暴露關(guān)于對(duì)象的存在與不存在的信息。同樣不明顯的是,透明地允許重新創(chuàng)建以前刪除的實(shí)例是比簡(jiǎn)單地返回404響應(yīng)更好的默認(rèn)行為。
兩種形式 "PUT as 404" 和 "PUT as create" 可以在不同的情況下有效,但從3.0版本起,我們現(xiàn)在使用 404作為默認(rèn)值,因?yàn)樗?jiǎn)單和更明顯。
如果你需要通用的 PUT-as-create行為,你可能想要包括像 這個(gè)AllowPUTAsCreateMixin 類 一樣的mixin在你的視圖里。
以下第三方包提供了其他通用視圖實(shí)現(xiàn)。
The django-rest-framework-bulk package 包實(shí)現(xiàn)通用視圖mixins以及一些常見的具體通用視圖,以允許通過(guò)API請(qǐng)求應(yīng)用批量操作。
Django Rest Multiple Models 提供了通過(guò)單個(gè)API請(qǐng)求發(fā)送多個(gè)序列化模型和/或者查詢集的通用視圖(和mixin)。
更多建議: