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

文章介绍了在DjangoRESTframework中如何自定义视图集的action方法,包括在视图逻辑中手写action,使用序列化器类,以及如何在路由表中定义新路由。同时,讨论了如何根据不同的action选择不同的序列化器类,并展示了如何通过action装饰器指定请求方法和详细视图设置。

之前我们的视图类可以继承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))
]

Django REST Framework(DRF)通过URL Router机制来实现路由匹配。路由器负责将HTTP请求映射到相应的视图函数或序列化器。以下是DRF路由的基本工作原理: 1. **URL配置**: 在`urls.py`文件中,你需要导入` routers`, `views` 和` urlpatterns`。然后创建一个`DefaultRouter`实例,并指定你要应用的视图。 ```python from rest_framework import routers from . import views router = routers.DefaultRouter() router.register(r'myapp', views.MyViewSet) # 注册视图集 urlpatterns = router.urls ``` 2. **路由模式**: 使用正则表达式定义URL模式,例如`r'^myapp/(?P<pk>[0-9]+)/$'`。`pk`是一个捕获组,用于匹配路径中的整数ID。 3. **视图函数匹配**: DRF会根据URL模式找到匹配的视图。对于上面的例子,当发送GET请求到`/myapp/1/`这样的URL时,`MyViewSet`的`list()`方法(针对所有对象)或`retrieve()`方法(针对单个对象,如ID为1)会被调用。 4. **视图处理器**: 视图集(ViewSet)包含了对各种HTTP方法(如GET、POST、PUT等)的支持。当你注册视图集时,DRF已经自动处理了这些方法的路由和请求处理。 5. **自定义路由**: 你可以通过重写`router.urls`或直接在`urlpatterns`中添加自定义URL模式,以便更精确地控制路由规则。 DRF允许你通过`action`属性为特定操作(如创建、更新、删除)定义单独的视图,也可以使用`lookup_field`设置不同类型的URL路径(如基于名称或slug)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高老庄里的高小翠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值