檢視元件(繼承不同類重寫檢視類第四層和第五層)、路由元件(修改路由的全部寫法)
阿新 • • 發佈:2022-04-01
今日內容概要
- 檢視元件
- 路由元件
內容詳細
1、檢視元件
# 9個檢視子類--是檢視類
from rest_framework.generics import
CreateAPIView,
ListAPIView,
DestroyAPIView,
RetrieveAPIView,
UpdateAPIView,
ListCreateAPIView,
RetrieveUpdateAPIView,
RetrieveUpdateDestroyAPIView,
RetrieveDestroyAPIView
第四層: 通過9個檢視子類,重寫檢視函式 views.py:
# 第四層:通過9個檢視子類,重寫檢視函式 # 9個檢視子類 from rest_framework.generics import CreateAPIView, ListAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView from rest_framework.generics import ListCreateAPIView, RetrieveUpdateAPIView, RetrieveUpdateDestroyAPIView, RetrieveDestroyAPIView class PublishView(ListCreateAPIView): # 查詢所有和新增介面就有了 # class PublishView(CreateAPIView): # 新增介面就有了 # class PublishView(ListAPIView): # 查詢所有介面就有了 queryset = Publish.objects.all() serializer_class = PublishSerialzier class PublishDetailView(RetrieveUpdateDestroyAPIView): # 查詢單條,刪除,修改 介面就都有了 # class PublishDetailView(RetrieveAPIView): # 查詢單條 介面就有了 # class PublishDetailView(DestroyAPIView): # 刪除 介面就有了 # class PublishDetailView(UpdateAPIView): # 修改 介面就有了 # class PublishDetailView(RetrieveDestroyAPIView): # 查詢單條和刪除 介面就有了 # class PublishDetailView(RetrieveUpdateAPIView): # 查詢單條和更新 介面就有了 # class PublishDetailView(UpdateAPIView,DestroyAPIView): # 更新和刪除 介面就有了 queryset = Publish.objects.all() serializer_class = PublishSerialzier # 但是頁有可能要重寫--》get_queryset--》get_serializer_class--》perform_create--》get,post等方法
第五層: 通過ViewSet,重寫檢視函式 views.py:
# 第五層:通過ViewSet寫檢視類 # 5個介面,都用一個檢視類----》導致了路由問題:有兩個get from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet """ from rest_framework.viewsets import ViewSet, GenericViewSet from rest_framework.viewsets import ViewSetMixin ViewSet=APIView+ViewSetMixin GenericViewSet=GenericAPIView+ViewSetMixin 以後只要想自動生成路由,必須繼承ViewSetMixin及其子類 之前的寫法可以沿用,只是如果要自動生成路由可以選擇繼承ViewSet 或者 GenericViewSet """ class PublishView(ModelViewSet): # 修改路由,5個介面都有 # 繼承了5個檢視擴充套件類+GenericViewSet(ViewSetMixin, generics.GenericAPIView) # 其中 ViewSetMixin-->控制了路由寫法變了 # class PublishView(ReadOnlyModelViewSet): # 修改路由,只有 查所有,查單個兩個介面 queryset = Publish.objects.all() serializer_class = PublishSerialzier ##### 在urls.py中配置 加入方式一: from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('publish', views.PublishView, 'publish') # 然後要把路由加入到urlpatterns的列表中 兩種方式 urlpatterns = [ path('admin/', admin.site.urls), path('books/', views.BookView.as_view()), path('books/<int:pk>', views.BookView.as_view()), ] # 加入方式一 # router.urls 他會自動生成列表 包含兩種地址: publishs / publishs/<int:pk> # print(router.urls) # [<URLPattern '^publish/$' [name='publish-list']>, <URLPattern '^publish/(?P<pk>[^/.]+)/$' [name='publish-detail']>] urlpatterns += router.urls # 兩個列表相加 ##### 在urls.py中配置 加入方式二: from django.urls import include from rest_framework.routers import SimpleRouter router = SimpleRouter() router.register('publish', views.PublishView, 'publish') # 然後要把路由加入到urlpatterns的列表中 兩種方式 urlpatterns = [ path('admin/', admin.site.urls), path('books/', views.BookView.as_view()), path('books/<int:pk>', views.BookView.as_view()), # 加入方式二: path('api/v1/', include(router.urls)), # from django.urls import include # 這樣寫等用於下面兩句 ''引號中可以隨意加入字首 # 但是預設就有: publishs / publishs/<int:pk> # path('api/v1/publishs/', views.PublishView.as_view()), # # path('api/v1/publishs/<int:pk>', views.PublishDetailView.as_view()), ]
2、路由元件
# 只要繼承ViewSetMixin 及其子類,路由寫法就變了
# 檢視類只要繼承ViewSetMixin,路由寫法就變了 而且檢視類中的方法不一定寫成get,post.. 可以隨意命名 路由改為:
path('login/', views.TestView.as_view({'get': 'login'})), # 意思為:get請求來了,執行檢視類中的login方法
# 如何執行的?原始碼分析
ViewSetMixin必須寫在前面
as_view--->類的查詢順序
actions就是傳入的字典---》view閉包函式:
def view(request, *args, **kwargs):
# get login
for method, action in actions.items():
# 把login方法的記憶體地址給了handler
handler = getattr(self, action)
# 通過反射,設定給get---》對應login---》get請求執行get方法,現在get方法變成了login方法
setattr(self, method, handler)
return self.dispatch(request, *args, **kwargs)# 跟之前一樣了
演示繼承 ViewSetMixin類 的路由寫法:
### views.py中:
from rest_framework.viewsets import ViewSetMixin, ViewSet, GenericViewSet
from rest_framework.views import APIView
from rest_framework.decorators import action
class TestView(ViewSetMixin, APIView): # ViewSetMixin必須寫在前面
# class TestView(ViewSet): # 等同於上面 class TestView(ViewSetMixin, APIView)
# class TestView(ViewSetMixin, GenericAPIView): # 只要繼承ViewSetMixin的 該類就必須寫在前面
def login(self, request):
return Response("get-login")
# 路由中 urls.py:
# 路由元件:
path('login/', views.TestView.as_view({'get': 'login'})), # 意思為:get請求來了,執行檢視類中的login方法
繼承ModelViewSet 類,路由寫法:
# views.py:
# 路由元件
class PublishView(ModelViewSet): # 修改路由,5個介面都有
queryset = Publish.objects.all()
serializer_class = PublishSerialzier
# urls.py:
path('publish/', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
path('publish/<int:pk>', views.PublishView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
總結:
# 上面的兩個路由,是可以自動生成的:
第一步:匯入drf提供的路由類
from rest_framework.routers import SimpleRouter
第二步:例項化得到物件
router = SimpleRouter()
第三步:註冊路由
router.register('地址', 檢視類, '別名')
router.register('publish', views.PublishView, 'publish')
第四步:在urlpatterns加入(兩種方式)
path('/api/v1', include(router.urls))
urlpatterns+=router.urls
# SimpleRouter類 和 DefaultRouter類
用法完全一樣 只是生成的路由不一樣
DefaultRouter 比 SimpleRouter多一條根地址,一般咱麼就用 SimpleRouter就可以
# 如果使用自動生成路由,必須繼承誰及其子類?
GenericViewSet + 5個檢視擴充套件類至少之一 才能自動生成
# action裝飾器
# action裝飾器 可以再生成路由 記得要修改路由為自動生成模式
from rest_framework.decorators import action
class TestView(ViewSetMixin, APIView): # ViewSetMixin必須寫在前面
# action的預設引數:
# methods=請求方法,列表, detail=是否帶id, url_path=地址如果不寫,預設已方法名為地址, url_name=別名
# 寫成如下,自動生成路由會生成一條路由:127.0.0.1:8080/test/login -->get,post都會觸發
@action(methods=['GET', 'POST'], detail=False)
def login(self, request):
return Response("get-login")
# 如果寫法如下,生成的路徑是127.0.0.1:8080/test/數字/login
@action(methods=['GET', 'POST'], detail=True)
def login(self, request):
# 使用action,怎麼通過action判斷?
重寫 get_queryset、get_serializer_class
class TestView2(GenericViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get_queryset(self):
# 根據請求地址,返回的get_queryset不一樣
if self.action=='login':
return Author.objects.all()
else:
return self.queryset
def get_serializer_class(self):
if self.action=='login':
return AuthorSerialzier
else:
return BookSerializer
@action(methods=['GET','POST'],detail=True)
def login(self,request):
obj=self.get_queryset()
return Response("get-login")
@action(methods=['GET'], detail=True)
def test1(self,request):
obj = self.get_queryset()
return Response("get-test1")