【DRF】DRF中的路由器机制

一、各种常见需求

需求1:获取项目信息,只输出项目的id和名称,并且不分页
视图:定义action方法

class ProjectsViewSet(viewsets.ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']

    pagination_class = PageNumberPagination


    def names(self,request,*args,**kwargs):
        queryset=self.get_queryset()

        names_list=[]
        for project in queryset:
            names_list.append({
    
    
                'id':project.id,
                'name':project.name
            })
        return Response(names_list,status=status.HTTP_200_OK)

定义路由:

定义到这里可以吗?
不可以,get重复了,冲突了

在这里插入图片描述

只能在重新定义路由条目了,如下

urlpatterns=[
    path('projects/',views.ProjectsViewSet.as_view({
    
    
        'get':'list',
        'post':'create'
    })),
    path('projects/<int:pk>/',views.ProjectsViewSet.as_view({
    
    
        'get':'retrieve',
        'put':'update',
        'patch':'partial_update',
        'delete':'destroy'
    })),
    path('projects/names/',views.ProjectsViewSet.as_view({
    
    
        'get':'names'
    })),
    
]

需求2:获取项目的所有接口信息
视图:定义action方法

class ProjectsViewSet(viewsets.ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']

    pagination_class = PageNumberPagination


    def names(self,request,*args,**kwargs):
        queryset=self.get_queryset()

        names_list=[]
        for project in queryset:
            names_list.append({
    
    
                'id':project.id,
                'name':project.name
            })
        return Response(names_list,status=status.HTTP_200_OK)

    def interfaces(self,request,*args,**kwargs):
        instance=self.get_object()
        interfacess=instance.interfaces_set.all()
        interfaces_list=[]
        for interface in interfacess:
            interfaces_list.append({
    
    
                'id':interface.id,
                'name':interface.name
            })
        return Response(interfaces_list)

定义路由:

 path('projects/',views.ProjectsViewSet.as_view({
    
    
        'get':'list',
        'post':'create',
        'get':'names',
    })),
    path('projects/<int:pk>/',views.ProjectsViewSet.as_view({
    
    
        'get':'retrieve',
        'put':'update',
        'patch':'partial_update',
        'delete':'destroy'
    })),
    path('projects/names/',views.ProjectsViewSet.as_view({
    
    
        'get':'names'
    })),
    path('projects/<int:pk>/interfaces/',views.ProjectsViewSet.as_view({
    
    
        'get':'interfaces'
    })),

痛点1:假如action方法有很多,6个路由条目都需要一一映射,再加上自定义的一些action方法,会麻烦。能不能自动生成路由条目,不需要自己定义。接下来就需要学习路由器机制,如下

二、路由器机制

如下是视图类中支持的所有的路由条目,涵盖了ModelViewSet中所有的action方法和自定义的action方法,会自动生成路由条目
在这里插入图片描述

1、可以使用路由器对象,只能为视图集类自动生成路由条目
2、路由器对象默认只为通用action(create、list、retrieve、update、destroy)生成路由条目,自定义的action方法不会自动生成路由条目
3、创建SimpleRouter路由对象
router=routers.SimpleRouter()
4、使用路由器对象调用register方法进行注册
5、prefix指定路由前缀
6、viewset指定视图集,不可调用as_view
7、方式一:path('',include(router.urls))生成路由条目
8、方式二router.urls为列表,urlpatterns+=router.urls
9、DefaultRouter与SimpleRouter的区别:功能类似,
router=routers.SimpleRouter()
router=routers.DefaultRouter()
仅有的区别:DefaultRouter会自动生成一个根路径(显示获取数据的路口)

from django.urls import re_path, path, include
from rest_framework import routers

from projects import views

#创建路由器对象
router=routers.SimpleRouter()
#注册路由
router.register(r'projects',views.ProjectsViewSet)

urlpatterns=[
    # path('projects/',views.ProjectsViewSet.as_view({
    
    
    #     'get':'list',
    #     'post':'create'
    # })),
    # path('projects/<int:pk>/',views.ProjectsViewSet.as_view({
    
    
    #     'get':'retrieve',
    #     'put':'update',
    #     'patch':'partial_update',
    #     'delete':'destroy'
    # })),
    # path('projects/names/',views.ProjectsViewSet.as_view({
    
    
    #     'get':'names'
    # })),
    # path('projects/<int:pk>/interfaces/',views.ProjectsViewSet.as_view({
    
    
    #     'get':'interfaces'
    # }))

    path('',include(router.urls))
]

痛点2:路由器对象默认只为通用action(create、list、retrieve、update、destroy)生成路由条目,自定义的action方法不会自动生成路由条目,如果解决这个问题需要要到action装饰器

使用装饰器为自定义的action方法,自动生成路由条目

1、如果需要使用路由器机制自动生成路由条目,那么就必须得使用action装饰器
2、methods指定需要搜使用的请求方法,如果不指定,默认为GET
3、detail指定是否为详情接口,是否需要传递当前模型的pk值
如果需要传递当前模型的pk值,那么detail=True,否则detail为False

针对上述需求1:获取项目信息,只输出项目的id和名称,并且不分页

定义视图类

class ProjectsViewSet(viewsets.ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']

    pagination_class = PageNumberPagination

    @action(methods=['GET'],detail=False)
    def names(self,request,*args,**kwargs):
        queryset=self.get_queryset()

        names_list=[]
        for project in queryset:
            names_list.append({
    
    
                'id':project.id,
                'name':project.name
            })
        return Response(names_list,status=status.HTTP_200_OK)

访问接口
在这里插入图片描述

针对上述需求2:获取项目的所有接口信息

class ProjectsViewSet(viewsets.ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']

    pagination_class = PageNumberPagination

    @action(methods=['GET'], detail=True)
    def interfaces(self,request,*args,**kwargs):
        instance=self.get_object()
        interfacess=instance.interfaces_set.all()
        interfaces_list=[]
        for interface in interfacess:
            interfaces_list.append({
    
    
                'id':interface.id,
                'name':interface.name
            })
        return Response(interfaces_list)

访问接口
在这里插入图片描述

装饰器中传入url_path、url_name参数的意义

4、url_path指定url路径,默认为action方法名称,一般不需要指定
5、url_name指定url路由条目名称后缀,默认为action方法名称,一般不需要指定

class ProjectsViewSet(viewsets.ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsSerializer

    filter_backends = [filters.SearchFilter, filters.OrderingFilter, DjangoFilterBackend]
    search_fields = ['name', 'leader', 'id']
    ordering_fields = ['name', 'leader', 'id']
    filterset_fields = ['name', 'leader']

    pagination_class = PageNumberPagination

    @action(methods=['GET'],detail=False,url_path='xxx',url_name='yyy')
    #@action(methods=['GET'],detail=False)
    def names(self,request,*args,**kwargs):
        queryset=self.get_queryset()

        names_list=[]
        for project in queryset:
            names_list.append({
    
    
                'id':project.id,
                'name':project.name
            })
        return Response(names_list,status=status.HTTP_200_OK)

在这里插入图片描述
访问接口url:http://192.168.17.129:8000/projects/xxx

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/YZL40514131/article/details/124812161
DRF
今日推荐