• 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']
    
  • 相关阅读:
    linux正则表达式
    linux监控值free命令详解
    loadrunner 中数组的定义
    管线工具sed和正则表达式
    web_link()参数化
    mysql执行插入时性能优化
    linux关闭防火墙
    linux系统中变量和环境变量
    mysql源码安装与基本优化配置
    Memory Consistency Erros
  • 原文地址:https://www.cnblogs.com/Yunya-Cnblogs/p/13906709.html
Copyright © 2020-2023  润新知