drf 路由生成
source link: http://www.cnblogs.com/Yunya-Cnblogs/p/13906709.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前言
在 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']
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK