drf 路由生成

前言

   在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,这是因为我们的APIlookup_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干什么用?是为了给继承自ViewSetMixin的视图类中定义的函数也添加路由,因为ViewSetMixin中有一个actions的参数,使用action就能够填入这个参数。

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)  # 还有个参数,url_path。匹配规则,默认是函数名,还有url_name,反向代理时的别名
    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']
原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13906709.html