前言
在drf
中,我們寫介面可以通過繼承modelViewSet
從而達到非常快速的功能實現,這十分的方便,但是modelViewSet
由於需要根據不同的引數來對應不同的處理,所以我們寫的url
最少都需要兩條,如下所示:
path('api/users/', views.UserAPI.as_view(actions={"get":"list","post":"create"})),
re_path('^api/users/(?P<uid>\d+)?',views.UserAPI.as_view(actions={"get":"retrieve","patch":"update","delete":"destroy"}))
有沒有什麼辦法能夠快速的生成兩條url
呢?其實是有的,但是在這之前我們也可以對他手動封裝一個元件,達到自動生成路由的功能。
手動封裝
下面是手動封裝url
的一個示例,首先url
本身就是一個列表,所以我們的元件最終可以返回一個可迭代物件就行,直接將生成的url
新增至已有的url
列表中。
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
from rest_framework.routers import SimpleRouter
class GenerateRouter:
def __init__(self):
self.urls = None
def register(self, prefix, viewset, basename=None):
# prefix 匹配規則,不用加 /
# viewset 繼承自ModelViewSet檢視類
# basename 別名
from django.urls import path, re_path
name = viewset.serializer_class.Meta.model.__name__.lower() # 獲取查詢的資料表名字
self.urls = (
re_path("^%s/$" % prefix, viewset.as_view(actions={"get": "list", "post": "create"}),
name=basename or name + "-list"), # 不需要引數,查全部和新增
re_path('^%s/(?P<%s>[^/.]+)/$' %(prefix,viewset.lookup_url_kwarg or "pk"), # 如果設定捕獲欄位,就用捕獲欄位,否則就用pk
viewset.as_view(
actions={"get": "retrieve", "patch": "update", "delete": "destroy", "put": "update"}),
name=basename or name + "-detail"),
)
router = GenerateRouter() # 例項化
router.register("api/users", views.UserAPI) # 註冊
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns.extend(router.urls) # 新增
它生成的路由是這樣子的:
^api/users/$ [name='user-list']
^api/users/(?P<uid>[^/.]+)/$ [name='user-detail']
router元件
簡單路由
在drf
中也提供了這樣的元件,它可以幫助我們快速的生成路由。比我們上面自己封裝的要強大一些,但是本質上都是一樣的。
下面是簡單使用,首先我們需要進行匯入。
from rest_framework.routers import SimpleRouter
其次是對其進行例項化後註冊一個路由資訊。
def register(self, prefix, viewset, basename=None)
# prefix 匹配規則,不用加 /
# viewset 繼承自ModelViewSet檢視類
# basename 別名
from django.contrib import admin
from django.urls import path
from app01 import views
from rest_framework.routers import SimpleRouter # 第一步匯入
router = SimpleRouter() # 第二步例項化
router.register("api/users", views.UserAPI) # 第三步註冊路由
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns.extend(router.urls) # 第四步新增
它會自動生成兩條url
,這與我們上面的手動封裝是一樣的原理:
^api/users/$ [name='user-list']
^api/users/(?P<uid>[^/.]+)/$ [name='user-detail']
至於這裡為什麼是uid
,這是因為我們的API
中lookup_url_kwarg
設定的就是uid
。
可以看以下上面手動封裝中,也是這麼做的。
class UserAPI(ModelViewSet):
queryset = models.User.objects # 傳入物件即可
serializer_class = ser.UserModelSerializers # 序列化類
lookup_field = "pk"
lookup_url_kwarg = "uid" # 由於捕獲的是uid,需要宣告
預設路由
簡單的SimpleRouter()
其實就足夠我們用了,但是drf
也提供了更高階的預設路由,它會生成六條url
,但是基本沒啥用。
from django.contrib import admin
from django.urls import path, re_path
from app01 import views
from rest_framework.routers import SimpleRouter
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register("api/users", views.UserAPI)
urlpatterns = [
path('admin/', admin.site.urls),
]
urlpatterns.extend(router.urls)
以下是生成的路由資訊。
^api/users/$ [name='user-list']
^api/users\.(?P<format>[a-z0-9]+)/?$ [name='user-list']
^api/users/(?P<uid>[^/.]+)/$ [name='user-detail']
^api/users/(?P<uid>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='user-detail']
^$ [name='api-root']
^\.(?P<format>[a-z0-9]+)/?$ [name='api-root']
action裝飾器
action
幹什麼用?是為了給繼承自ModelViewSet
的檢視類中定義的函式也新增路由。
from . import models
from . import ser
from rest_framework.decorators import action # 匯入裝飾器
from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
class UserAPI(ModelViewSet):
queryset = models.User.objects.all() # 傳入物件即可
serializer_class = ser.UserModelSerializers # 序列化類
lookup_field = "pk"
lookup_url_kwarg = "uid" # 由於捕獲的是uid,需要宣告
@action(methods=['GET','POST'],detail=True)
def customize(self,request,uid):
book=self.get_queryset()[:2] # 從0開始擷取一條
serializer=self.get_serializer(book,many=True) # 只要是返回queryset物件,就需要many=True
return Response(serializer.data)
# action的執行會覆蓋掉本身的get、post、patch等所執行的方法,如list,update,create等預設行為。
# methods代表請求方式,當有該種請求到來時,則執行該方法
# detail代表是否需要捕獲引數,True則是捕獲。捕獲引數名字就是lookup_url_kwarg
生成的路由資訊如下:
^api/users/(?P<uid>[^/.]+)/customize/$ [name='user-customize']
^api/users/(?P<uid>[^/.]+)/customize\.(?P<format>[a-z0-9]+)/?$ [name='user-customize']