DjangoRestFramework檢視和路由
阿新 • • 發佈:2018-12-12
一、restfull規範的簡單介紹
1、介紹
REST:表述性狀態轉移,是一種web互動方案
資源:在web中只要有被引用的必要都是資源
URI:
URI 統一資源識別符號
URL 統一資源定位符
統一資源介面
根據HTTP請求方式的不同對資源進行不同的操作
遵循HTTP請求方式的語義
前後端傳輸的叫資源的表述
前端展現的叫資源的狀態
通過超連結的指引告訴使用者接下來有哪些資源狀態可以進入
2、restfull規範
核心思想 -- 面向資源去程式設計 每個url就是資源的體現 儘量用名詞不要用動詞 -- 根據HTTP請求方式的不同對資源進行不同的操作 URL體現-- 版本 https://v3.bootcss.com https://bootcss.com/v3 -- 體現是否是API https://v3.bootcss.com/api -- 過濾資訊 https://v3.bootcss.com?page=1 -- 儘量用HTTPS 返回值體現 -- 攜帶狀態碼 -- 攜帶錯誤資訊 -- 返回值 get 返回檢視的所有或者單條資訊 post 返回新增的那條資料 put/patch 返回更新那條資料 delete 返回空-- 攜帶超連結
二、DRF的檢視的封裝
1、為什麼要封裝
當有很多個表進行增刪改查時,實際上很多程式碼都是相同的,只是要獲取的queryset和序列化器等不同,這就導致我們的檢視有特別多重複的程式碼,
因此對檢視進行封裝,可減少程式碼的冗餘。
2、要封裝的原檢視
class BookView(APIView): def get(self, request): book_queryset = Book.objects.all() ser_obj = BookSerializer(book_queryset, many=True)View Codereturn Response(ser_obj.data) # 新增書籍 def post(self, request): book_obj = request.data ser_obj = BookSerializer(data=book_obj) if ser_obj.is_valid(): ser_obj.save() print(ser_obj.validated_data) return Response(ser_obj.data) # 校驗不通過返回錯誤資訊 return Response(ser_obj.errors) # 編輯書籍 class BookEditView(APIView): def get(self, request, id): book_obj = Book.objects.filter(pk=id).first() ser_obj = BookSerializer(book_obj) return Response(ser_obj.data) def put(self, request, id): book_obj = Book.objects.filter(id=id).first() ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True) if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) return Response(ser_obj.errors) def delete(self, request, id): book_obj = Book.objects.filter(id=id).first() if book_obj: book_obj.delete() return Response('') return Response('刪除物件不存在')
3、第一次封裝
# 獲取query_set和序列化器的類 class GenericAPIView(APIView): query_set = None serializer_class = None def get_queryset(self): return self.query_set def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) # 實現get方法的類 # 小知識點:一般Mixin代表的是混合類,單獨繼承ListModelMixin你去哪裡找get_queryset方法 # 因此,其他類繼承Mixin類的時候,還應該多繼承其他的某些類 class ListModelMixin(object): def list(self, request): queryset = self.get_queryset() ser_obj = self.get_serializer(queryset, many=True) return Response(ser_obj.data) # 實現post方法的類 class CreateModelMixin(object): def create(self, request): # 獲取前端傳過來的資料 obj = request.data # 用序列化器做校驗 ser_obj = self.get_serializer(data=obj) if ser_obj.is_valid(): # 校驗通過,新增書籍 ser_obj.save() # 這裡的save方法會去呼叫序列化器的create方法 print(ser_obj.validated_data) # validated_data是通過校驗的資料,也會封裝到data裡面 return Response(ser_obj.data) # 校驗不通過返回錯誤資訊 return Response(ser_obj.errors) # 實現編輯的get方法的類 class RetrieveModelMixin(object): def retrieve(self, request, id): book_obj = self.get_queryset().filter(pk=id).first() ser_obj = self.get_serializer(book_obj) return Response(ser_obj.data) # 實現編輯的put方法的類 class UpdateModelMixin(object): def update(self, request, id): book_obj = self.get_queryset().filter(id=id).first() ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True) if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) return Response(ser_obj.errors) # 實現刪除delete方法的類 class DestroyModelMixin(object): def destroy(self, request, id): book_obj = self.get_queryset().filter(id=id).first() if book_obj: book_obj.delete() return Response("") return Response("刪除的物件不存在") # 書籍列表 class BookView(GenericAPIView,ListModelMixin, CreateModelMixin): query_set = Book.objects.all() serializer_class = BookSerializer def get(self, request): return self.list(request) def post(self, request): return self.create(request) class BookEditView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): query_set = Book.objects.all() serializer_class = BookSerializer def get(self, request, id): return self.retrieve(request, id) def put(self, request, id): return self.update(request, id) def delete(self, request, id): return self.destroy(request, id)View Code
4、第二次封裝
由於上面的繼承太長了,因此我們細化一點點,其實就是在第一次封裝的基礎上另外設定一些類來進行了繼承。
# 獲取query_set和序列化器的類 class GenericAPIView(APIView): query_set = None serializer_class = None def get_queryset(self): return self.query_set def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) # 實現get方法的類 # 小知識點:一般Mixin代表的是混合類,單獨繼承ListModelMixin你去哪裡找get_queryset方法 # 因此,其他類繼承Mixin類的時候,還應該多繼承其他的某些類 class ListModelMixin(object): def list(self, request): queryset = self.get_queryset() ser_obj = self.get_serializer(queryset, many=True) return Response(ser_obj.data) # 實現post方法的類 class CreateModelMixin(object): def create(self, request): # 獲取前端傳過來的資料 obj = request.data # 用序列化器做校驗 ser_obj = self.get_serializer(data=obj) if ser_obj.is_valid(): # 校驗通過,新增書籍 ser_obj.save() # 這裡的save方法會去呼叫序列化器的create方法 print(ser_obj.validated_data) # validated_data是通過校驗的資料,也會封裝到data裡面 return Response(ser_obj.data) # 校驗不通過返回錯誤資訊 return Response(ser_obj.errors) # 實現編輯的get方法的類 class RetrieveModelMixin(object): def retrieve(self, request, id): book_obj = self.get_queryset().filter(pk=id).first() ser_obj = self.get_serializer(book_obj) return Response(ser_obj.data) # 實現編輯的put方法的類 class UpdateModelMixin(object): def update(self, request, id): book_obj = self.get_queryset().filter(id=id).first() ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True) if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) return Response(ser_obj.errors) # 實現刪除delete方法的類 class DestroyModelMixin(object): def destroy(self, request, id): book_obj = self.get_queryset().filter(id=id).first() if book_obj: book_obj.delete() return Response("") return Response("刪除的物件不存在") # 繼承上面需要的類,別的類只需繼承這個類即可使用這個類繼承的方法 class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin): pass class RetrieveUpdateDestroyModelMixin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): pass # 書籍列表 class BookView(ListCreateModelMixin): query_set = Book.objects.all() serializer_class = BookSerializer def get(self, request): return self.list(request) def post(self, request): return self.create(request) class BookEditView(RetrieveUpdateDestroyModelMixin): query_set = Book.objects.all() serializer_class = BookSerializer def get(self, request, id): return self.retrieve(request, id) def put(self, request, id): return self.update(request, id) def delete(self, request, id): return self.destroy(request, id)View Code
5、第三次封裝
1. DRF框架的ViewSetMixin類重寫了CBV的as_view方法,使其可以接收引數,路由分發的時候會根據引數進行分發, 繼承了ViewSetMixin的類,它的路由as_view可以傳參 2. urls.py from django.conf.urls import url from libsys import views urlpatterns = [ url(r'^list/$', views.BookModelView.as_view({"get": "list", "post": "create"})), url(r'^retrieve/(?P<id>\d+)/$', views.BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ] 3. 第三次封裝 from rest_framework.viewsets import ViewSetMixin # 重寫as_view使其可以傳參 # Create your views here. # 獲取query_set和序列化器的類 class GenericAPIView(APIView): query_set = None serializer_class = None def get_queryset(self): return self.query_set def get_serializer(self, *args, **kwargs): return self.serializer_class(*args, **kwargs) # 實現get方法的類 # 小知識點:一般Mixin代表的是混合類,單獨繼承ListModelMixin你去哪裡找get_queryset方法 # 因此,其他類繼承Mixin類的時候,還應該多繼承其他的某些類 class ListModelMixin(object): def list(self, request): queryset = self.get_queryset() ser_obj = self.get_serializer(queryset, many=True) return Response(ser_obj.data) # 實現post方法的類 class CreateModelMixin(object): def create(self, request): # 獲取前端傳過來的資料 obj = request.data # 用序列化器做校驗 ser_obj = self.get_serializer(data=obj) if ser_obj.is_valid(): # 校驗通過,新增書籍 ser_obj.save() # 這裡的save方法會去呼叫序列化器的create方法 print(ser_obj.validated_data) # validated_data是通過校驗的資料,也會封裝到data裡面 return Response(ser_obj.data) # 校驗不通過返回錯誤資訊 return Response(ser_obj.errors) # 實現編輯的get方法的類 class RetrieveModelMixin(object): def retrieve(self, request, id): book_obj = self.get_queryset().filter(pk=id).first() ser_obj = self.get_serializer(book_obj) return Response(ser_obj.data) # 實現編輯的put方法的類 class UpdateModelMixin(object): def update(self, request, id): book_obj = self.get_queryset().filter(id=id).first() ser_obj = self.get_serializer(instance=book_obj, data=request.data, partial=True) if ser_obj.is_valid(): ser_obj.save() return Response(ser_obj.data) return Response(ser_obj.errors) # 實現刪除delete方法的類 class DestroyModelMixin(object): def destroy(self, request, id): book_obj = self.get_queryset().filter(id=id).first() if book_obj: book_obj.delete() return Response("") return Response("刪除的物件不存在") # 繼承上面需要的類,別的類只需繼承這個類即可使用這個類繼承的方法 class ListCreateModelMixin(GenericAPIView,ListModelMixin, CreateModelMixin): pass class RetrieveUpdateDestroyModelMixin(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin): pass # 五合一的檢視 # ViewSetMixin必須在GenericAPIView前面,因為需要ViewSetMixin先做路由的分發 class ModelViewSet(ViewSetMixin, ListCreateModelMixin, RetrieveUpdateDestroyModelMixin): pass class BookModelView(ModelViewSet): # 這裡什麼都不用寫了,因為as_view重寫後,某個請求進來會預設去找它對應的方法 # 這裡找不到,就會去父類中找 query_set = Book.objects.all() serializer_class = BookSerializerView Code
6、使用DRF框架幫我們封裝好的模組
1. 直接使用DRF自帶的ModelViewSet(DRF的ModelViewSet也是繼承了ViewSetMixin和那6個方法的類) 注意: DRF中使用queryset,我們自定義的是query_set 用框架封裝的檢視,我們url上的那個關鍵字引數要用pk,系統預設的 2. urls.py from django.conf.urls import url from libsys import views urlpatterns = [ url(r'^list/$', views.BookModelView.as_view({"get": "list", "post": "create"})), url(r'^retrieve/(?P<pk>\d+)/$', views.BookModelView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})), ] 3. 檢視 from rest_framework.viewsets import ModelViewSet # 這裡的ModelViewSet是DRF給我們的類 class BookModelView(ModelViewSet): queryset = Book.objects.all() serializer_class = BookSerializer
7、封裝圖解
三、路由
from rest_framework.routers import DefaultRouter
# 第一步例項化物件
router = DefaultRouter()
# 第二步把路由以及檢視註冊到物件
router.register('list', BookModelView) # 路徑,檢視
urlpatterns += router.urls