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

简介: 【Django学习】(十四)自定义action_router

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

自定义action

1、手写视图逻辑

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

class ProjectsViewSet(
    viewsets.ModelViewSet):
    # 指定当前类视图需要使用的查询集
    queryset = ProjectsModel.objects.all()
    # 指定当前类视图需要使用的序列化器类
    serializer_class = ProjectModelSerializer
    # lookup_field = 'Id'
    # 声明需要使用的引擎类
    filter_backends = [filters.SearchFilter,
                       filters.OrderingFilter
                       ]
    # 定义需要过滤的字段
    search_fields = ['name', 'id']
    # 定义需要排序的字段
    ordering_fields = ['id', 'name']
    # 声明需要使用的分页引擎
    pagination_class = PageNumberPagination
    @action(methods=['GET', 'POST'], detail=False)
    def names(self, request, *args, **kwargs):
        qs = self.get_queryset()
        lst = []
        for obj in qs:
            dict = {
                'id': obj.id,
                'name': obj.name,
            }
            lst.append(dict)
        return Response(lst, content_type='application/json')

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

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

支持get和post请求方式

2、使用序列化器类

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

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

2.2路由表定义路由

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

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

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

from .serializers import ProjectNameSerializer
    @action(methods=['GET', 'POST'], detail=False)
    def names(self, request, *args, **kwargs):
        qs = self.get_queryset()
        # lst = []
        # for obj in qs:
        #     dict = {
        #         'id': obj.id,
        #         'name': obj.name,
        #     }
        #     lst.append(dict)
        # return Response(lst, content_type='application/json')
        serializer_obj = ProjectNameSerializer(instance=qs, many=True)
        return Response(serializer_obj.data, status=status.HTTP_200_OK)

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

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

from rest_framework import routers
router = routers.SimpleRouter()
# 注册路由
router.register(r'projects', views.ProjectsViewSet)
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路径的名称

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

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

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

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

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

from rest_framework import routers
router = routers.SimpleRouter()
# 注册路由
router.register(r'projects', views.ProjectsViewSet)
urlpatterns = [
          path('', include(router.urls))
]

相关文章
|
12月前
|
缓存 监控 中间件
Django中间件自定义开发指南:从原理到实战的深度解析
Django中间件是Web应用的“交通警察”,在请求与响应过程中进行全局处理,适用于身份验证、日志记录、性能监控等功能。本文详解中间件的工作原理、开发步骤及实战案例,帮助开发者掌握自定义中间件的构建方法,提升Django应用的可维护性与扩展性。
583 0
|
Shell 数据库 网络架构
Django+DRF 实战:从异常捕获到自定义错误信息(下)
本文详解了 Django REST Framework 中 ValidationError 的验证流程与优先级,涵盖字段内置验证、自定义验证方法、对象级验证及数据库约束,并通过实战演示如何自定义异常提示信息。
308 1
Django+DRF 实战:从异常捕获到自定义错误信息(下)
|
Python
Django+DRF 实战:自定义异常处理流程
本文详解DRF异常处理流程,包括默认处理机制与自定义异常处理器的实现方法。通过源码分析和实战示例,讲解如何全局捕获并统一返回错误信息,并结合日志记录与友好提示提升项目健壮性。适用于Django进阶开发。
400 4
|
中间件 数据库 Python
Django实战:自定义中间件实现全链路操作日志记录
Django中间件是一套轻量级插件系统,用于全局处理请求与响应。通过自定义中间件可实现如操作日志记录等功能,支持在请求、视图、响应及异常阶段插入逻辑。本文详解中间件生命周期、编写方式及实战案例。
320 1
|
数据安全/隐私保护 网络架构 UED
Django+DRF 实战:从异常捕获到自定义错误信息
本文介绍了DRF(Django REST framework)中的异常处理机制,重点讲解了内置异常类ValidationError的使用场景与示例。同时通过用户注册功能的实战演示,展示了如何在序列化器中自定义参数校验规则,并在视图中捕获并返回结构化的错误信息,提升接口的健壮性与用户体验。
284 0
|
编解码 前端开发 JavaScript
技术经验分享:Django学习日记
技术经验分享:Django学习日记
|
IDE 关系型数据库 MySQL
Django学习一:创建Django框架,介绍Django的项目结构和开发逻辑。创建应用,编写主包和应用中的helloworld
这篇文章是关于如何创建一个Django框架,介绍Django的项目结构和开发逻辑,并指导如何创建应用和编写“Hello, World!”程序的教程。
957 3
Django学习一:创建Django框架,介绍Django的项目结构和开发逻辑。创建应用,编写主包和应用中的helloworld
|
SQL Java 数据库
Django学习三:views业务层中通过models对实体对象进行的增、删、改、查操作。
这篇文章是关于如何使用Django框架的ORM系统在视图(views)层面进行数据库的增、删、改、查操作的教程。
223 0
Django学习三:views业务层中通过models对实体对象进行的增、删、改、查操作。
|
关系型数据库 MySQL Java
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
这篇文章是关于如何使用Django框架配置MySQL数据库,创建模型实例,并自动或手动创建数据库表,以及对这些表进行操作的详细教程。
1118 0
Django学习二:配置mysql,创建model实例,自动创建数据库表,对mysql数据库表已经创建好的进行直接操作和实验。
|
安全 数据库 数据安全/隐私保护