当前位置:   article > 正文

【Django学习】(十四)自定义action_router_django modelviewset有哪些 @action

django modelviewset有哪些 @action

之前我们的视图类可以继承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. ]
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/44715
推荐阅读
相关标签
  

闽ICP备14008679号