幾種view以及他們之間的關係
View是Django中的
APIView
APIView是對Django中View的封裝,和View相比,APIView大致有以下不同:
1.傳遞給處理方法的請求是DRF的Request實例,而不是Django的HttpRequest實例;
2.響應並返回的是DRF的Response對象,而不是Django的HttpResponse對象;
4.會對接收的請求進行身份認證、權限的檢查以及限制訪問次數。
APIView使用方法如下:
from rest_framework.views import APIView
from rest_framework.response import Response
class SchoolView(APIView):
def get(self, request, *args, **kwargs):
query_set = models.School.objects.all()
ser_obj = app01_serializers.SchoolSerializer(query_set, many=True)
return Response(ser_obj.data)
GenericApiView
GenericApiView繼承於APIView,爲常用的列表視圖和詳細視圖提供了一些操作屬性方法。
示例:
from rest_framework import generics
from rest_framework import mixins
class SchoolView(GenericAPIView, mixins.ListModelMixin):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
GenericAPIView對APIView再次封裝,加入了以下功能:
- 加入queryset屬性,可以直接設置這個屬性,不必再將實例化的courses,再次傳給seriliazer,系統會自動檢測到。除此之外,可以重載get_queryset(),這樣就不必設置’queryset=*’,這樣就變得更加靈活,可以進行完全的自定義。
- 加入serializer_class屬性與實現get_serializer_class()方法。兩者的存在一個即可,通過這個,在返回時,不必去指定某個serilizer
- 設置過濾器模板:filter_backends(排序,過濾,搜索)
- 設置分頁模板:pagination_class
- 加入 lookup_field=”pk”,以及實現了get_object方法: 這個用得場景不多,但十分重要。它們兩者的關係同1,要麼設置屬性,要麼重載方法。它們的功能在於獲取某一個實例時,指定傳進來的後綴是什麼。
通常GenericAPIView不會單獨使用,GenericAPIView需要和Mixins組合使用。
Mixin類中提供了許多用於對視圖進行操作的方法,這些操作方法無須我們自己實現就可以使用了。比如,ListModelMixin
提供了一個list()
方法用於將Model的查詢集響應給客戶端。
在generics.py文件中還存在一些通用類,可以使代碼的編寫更加簡單。
簡化之後如下:
class SchoolView(ListCreateAPIView):
#使用通用類
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
GenericViewSet
GenericViewSet繼承了ViewSetMixin和GenericAPIView,在ViewSetMixin類中重寫了as_view方法,可以這樣使用路由:
url(r'school/$', views.SchoolView.as_view({
"get": "list",
"post": "create",
})),
視圖集ModelViewSet
集成了上面所有的類,非常好用
class SchoolView(ModelViewSet):
queryset = models.School.objects.all()
serializer_class = app01_serializers.SchoolSerializer
高級路由
route方法註冊與綁定
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'school', views.SchoolView)
urlpatterns += router.urls
route中使用的一定要是ViewSet,用router.register的方法註冊url可以很好的管理url,不會導致url過多而混亂。
補充:DRF中的Request和Resopnse
1. Request
在DRF中內置的Request類擴展了Django中的Request類,實現了很多方便的功能--如請求數據解析和認證等。
Request對象的數據是自動根據前端發送數據的格式進行解析之後的結果。
無論前端發送的哪種格式的數據,我們都可以以統一的方式讀取數據。
常用屬性
- .data
request.data 返回解析之後的請求體數據。類似於Django中標準的request.POST和 request.FILES屬性,但提供如下特性:
包含了解析之後的文件和非文件數據
包含了對POST、PUT、PATCH請求方式解析後的數據
利用了DRF的parsers解析器,不僅支持表單類型數據,也支持JSON數據
- .query_params
request.query_params與Django標準的request.GET相同,只是更換了更正確的名稱而已。
2 Response
DRF提供了一個響應類Response,使用該類構造響應對象時,響應的具體數據內容會被轉換(render渲染)成符合前端需求的類型。
DRF提供了Renderer 渲染器,用來根據請求頭中的Accept(接收數據類型聲明)來自動轉換響應數據到對應格式。如果前端請求中未進行Accept聲明,則會採用默認方式處理響應數據,可以通過配置來修改默認響應格式。
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': ( # 默認響應渲染類
'rest_framework.renderers.JSONRenderer', # json渲染器
'rest_framework.renderers.BrowsableAPIRenderer', # 瀏覽API渲染器
)
}
構造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)
參數:
data: 爲響應準備的序列化處理後的數據;
status: 狀態碼,默認200;
template_name: 模板名稱,如果使用HTMLRenderer 時需指明;
headers: 用於存放響應頭信息的字典;
content_type: 響應數據的Content-Type,通常此參數無需傳遞,REST framework會根據前端所需類型數據來設置該參數。
常用屬性:
- .data
傳給response對象的序列化後,但尚未render處理的數據
- .status_code
狀態碼的數字
- .content
經過render處理後的響應數據
- 3. 狀態碼
返回狀態信息。