• 【Django学习】(十四)自定义action_router


    之前我们的视图类可以继承GenericViewSet或者ModelViewSet,我们不用再自定义通用的action方法,但是有时候我们需要自定义action,我们该如何设计呢?

    自定义action

    1、手写视图逻辑

    1.1、先在视图集里自定义action方法,名称为names

    1. class ProjectsViewSet(
    2. viewsets.ModelViewSet):
    3. # 指定当前类视图需要使用的查询集
    4. queryset = ProjectsModel.objects.all()
    5. # 指定当前类视图需要使用的序列化器类
    6. serializer_class = ProjectModelSerializer
    7. # lookup_field = 'Id'
    8. # 声明需要使用的引擎类
    9. filter_backends = [filters.SearchFilter,
    10. filters.OrderingFilter
    11. ]
    12. # 定义需要过滤的字段
    13. search_fields = ['name', 'id']
    14. # 定义需要排序的字段
    15. ordering_fields = ['id', 'name']
    16. # 声明需要使用的分页引擎
    17. pagination_class = PageNumberPagination
    18. @action(methods=['GET', 'POST'], detail=False)
    19. def names(self, request, *args, **kwargs):
    20. qs = self.get_queryset()
    21. lst = []
    22. for obj in qs:
    23. dict = {
    24. 'id': obj.id,
    25. 'name': obj.name,
    26. }
    27. lst.append(dict)
    28. return Response(lst, content_type='application/json')

    1.2、在路由表url.py中定义新的路由

    1. urlpatterns = [
    2. path('projects/names/',views.ProjectsViewSet.as_view({'get':'names','post':'names'})),
    3. ]

     支持get和post请求方式

     

     2、使用序列化器类

    2.1创建一个新的序列化器类

    1. class ProjectNameSerializer(serializers.ModelSerializer):
    2. class Meta:
    3. model = ProjectsModel
    4. fields = ('id', 'name')

    2.2路由表定义路由

    1. urlpatterns = [
    2. path('projects/names/',views.ProjectsViewSet.as_view({'get':'names','post':'names'})),
    3. ]

    仅仅只有视图集继承Viewset或者GenericViewset之后,才具备方法名与action进行一一对应的功能 

    2.3 重写视图类中的自定义action方法

    1. from .serializers import ProjectNameSerializer
    2. @action(methods=['GET', 'POST'], detail=False)
    3. def names(self, request, *args, **kwargs):
    4. qs = self.get_queryset()
    5. # lst = []
    6. # for obj in qs:
    7. # dict = {
    8. # 'id': obj.id,
    9. # 'name': obj.name,
    10. # }
    11. # lst.append(dict)
    12. # return Response(lst, content_type='application/json')
    13. serializer_obj = ProjectNameSerializer(instance=qs, many=True)
    14. return Response(serializer_obj.data, status=status.HTTP_200_OK)

     2.4 将ProjectNameSerializer抽离出来,并且重写get_serializer_class方法

    • 如果当前类视图中,使用了多个不同的序列化器类,那么可以将get_serializer_class重写
    • 继承视图集类之后,会提供action属性,指定当前请求的action方法名称
    • 可以根据不同的action去选择不同的序列化器类(不同的查询集)
    1. @action(methods=['GET', 'POST'], detail=False)
    2. def names(self, request, *args, **kwargs):
    3. qs = self.get_queryset()
    4. serializer_obj=self.get_serializer(instance=qs, many=True)
    5. return Response(serializer_obj.data, status=status.HTTP_200_OK)
    6. def get_serializer_class(self):
    7. if self.action=='names':
    8. return ProjectNameSerializer
    9. return self.serializer_class

     如果请求的是/projects/names/,使用的是自定义的序列化器类进行数据输出

     如果请求的是其他路由路径,能够使用全局指定的序列化器类(serializer_class=ProjectModelSerializer)正常处理数据,进行序列化输出

    •  可以使用action装饰器,指定自定义action方法(使用路由器时,会自动生成路由条目)
    • 如果不指定methods,那么当前action只支持GET方法请求
    • 可以指定当前action支持多个请求方法,需要将请求方法大写添加至列表中
    • detail指定当前action是否为详情视图
    • url_path指定url的路径字符串
    • url_name指定url路径的名称
    • 如果不指定url_path和url_name,默认为action方法名称

     注册路由

    在路由表中导入routers

    1. from rest_framework import routers
    2. router = routers.SimpleRouter()
    3. # 注册路由
    4. router.register(r'projects', views.ProjectsViewSet)
    5. urlpatterns = router.urls

     注册路由:

    • 仅仅只有视图集才支持定义路由器功能
    • register方法可以注册路由条目
    • 第一个参数为路由条目的前缀,往往需要添加r'子应用名'
    • 第二个参数为视图集对象,无需调用as_view({})
    •  可以定义DefaultRouter对象,相比SimpleRouter路由对象,会自动添加一个根路由(指定当前项目的入口地址)
      • router = routers.DefaultRouter()

     

    如果没有指定url_path和url_name,则通过路由名称去获取URL路径

     如果在action里指定了url_path和url_name,则url_path指定url的路径字符串,url_name指定url路径的名称

    1. @action(methods=['GET', 'POST'], detail=False,url_path='na', url_name='an')
    2. def names(self, request, *args, **kwargs):
    3. qs = self.get_queryset()

     

     有时候,有些路由我们不想通过路由器生成,需要在urlpatterns里生成

    方式一:可以附加router.urls到现有视图的列表.

    1. from rest_framework import routers
    2. router = routers.SimpleRouter()
    3. # 注册路由
    4. router.register(r'projects', views.ProjectsViewSet)
    5. urlpatterns = []
    6. urlpatterns += router.urls

    方式二:或者可以使用 Django 的include函数,就像这样

    1. from rest_framework import routers
    2. router = routers.SimpleRouter()
    3. # 注册路由
    4. router.register(r'projects', views.ProjectsViewSet)
    5. urlpatterns = [
    6. path('', include(router.urls))
    7. ]
  • 相关阅读:
    influxDB学习笔记
    java 集合转换、查找、过滤、分割
    redis 高级数据类型之 HyperLogLog 算法详细介绍
    【unity与android的交互(一)】安卓打包相关的常见参数详解
    汽车蓄电池
    Tomcat 的连接器是如何设计的(上)
    学C++从CMake学起
    小程序源码:恋爱小助手-多玩法安装简单
    nginx设置开启自启动
    Selenium教程:自动化浏览器测试工具
  • 原文地址:https://blog.csdn.net/weixin_43569834/article/details/131722624