Bootstrap

一、视图类、视图集

View类

代码

以下代码:参考笔记【1】request获取请求参数 :https://blog.csdn.net/Ataoker/article/details/130739635

from django.views import View
import json
from rest_framework.response import Response   # 这个用不了,APIView才能用
from django.http import  HttpResponse,JsonResponse

class IndexView(View):
    def get(self,request, *args, **kwargs):
        return JsonResponse({"this":"get()",
                             "msg":f"你的请求方法是{request.method}",
                             "【GET请求__常规的路径参数】常规获取参数方式":request.GET['name'],
                             "【GET请求__常规的路径参数】常规获取参数方式2":request.GET.get('name',None),     # 推荐这种
                             "【GET请求__常规的路径参数】常规获取参数方式3":request.GET.getlist('name')
        })

    def post(self,request, *args, **kwargs):
        return JsonResponse({"this":"post()",
                             "msg": f"你的请求方法是{request.method}",
                             "msg2": f"请求头Content_type是 {request.headers['Content-Type']}",
                             "【GET请求__常规的路径参数】常规获取参数方式2": request.GET.get('name', None),
                             "【POST请求__body中json字符串】常规获取参数方式___json字符串": f"内容是:{request.body}",
                             "【POST请求__body中json字符串】常规获取参数方式___字典": json.loads(request.body)
                             })

    # def post(self, request, *args, **kwargs):
    #     return JsonResponse({"this": "psot()",
    #                          "msg": f"你的请求方法是{request.method}",
    #                          "msg2":f"请求头Content_type是 {request.headers['Content-Type']}",
    #                          "【GET请求__常规的路径参数】常规获取参数方式2": request.GET.get('name', None),
    #                          "【POST请求__x-www-form-urlencoded表单数据】常规获取参数方式1": request.POST.get('username', None),
    #                          "【POST请求__x-www-form-urlencoded表单数据】常规获取参数方式2": request.POST["password"],
    #                          })

    def put(self, request, *args, **kwargs):
        return JsonResponse({"this": "psot()","msg": f"你的请求方法是{request.method}"})

    def delete(self, request,*args, **kwargs):
        return JsonResponse({"this":"delete()","msg": f"你的请求方法是{request.method}"})

"""
url.py中,配置    path('test/',views.IndexView.as_view())
"""

验证代码作用

传递不同的请求方法,来验证View的功能
GET : http://127.0.0.1:8000/test/?name=xiaoli
POST(Content-Type:application/json ): http://127.0.0.1:8000/test/?name=xiaoli

  • body中: {“age”:18}

POST(application/x-www-form-urlencoded): http://127.0.0.1:8000/test/?name=xiaoli

  • 表单中 :username :taoke password : 123456

View类的效果展示:

getGET

post的json
在这里插入图片描述
post的表单
在这里插入图片描述

drf中最基础的视图类----APIView

它是继承了 View。所以可以定义get,post,put方法等

特点1:统一获取请求参数的方式

  • get的 ?neme=xxx 参数,除了用 request.GET.get(“xx”) , 或者用 request.query_params.get(“xx”)
  • post请求的 表单格式,或者是json格式数据,都可以用request.data (得到的是字典的形式) 来获取 数据。
    • 好处:使用这个代码后,一种代码就能拿到不管是表单,不管是json格式的数据(表单组成字典, json字符串直接转成字典)

get
在这里插入图片描述

post的表单,这样请求,content-type会默认为表单在这里插入图片描述

post的json,这样请求,content-type会默认为json在这里插入图片描述
补充:如果是函数视图,可以加装饰器@api_view([‘POST’,‘GET’]), ---------->功能有点像APIview

  • 函数中使用request.data 也能获取到body中的数据,
  • 可以使用Resonse 进行返回(会渲染成网页)

特点2:可配置解析器

  • 可以统一使用request.data 来获取 请求参数(有了这个解析器,才有特点1)
  • 可以配置 默认解析器(DEFAULT_PARSER_CLASSES),来控制允许解析哪种请求参数。

rest_framework中的默认解析器,配置有三种(下图是源码restframework中的setting):
在这里插入图片描述
在这里插入图片描述

1. 全局配置

django提供了一个方式,就是可以不修改源码,而是在项目setting中进行修改, 写在如下 字典中、

REST_FRAMEWORK = {}

把以下放进去就可以

'DEFAULT_PARSER_CLASSES': [
    'rest_framework.parsers.JSONParser',
    'rest_framework.parsers.FormParser',        # 假如不允许传这种就注释它, 想要传其他的,如xml,就要想办法加上
    'rest_framework.parsers.MultiPartParser'
],

如下:进行了全局配置后的效果
在这里插入图片描述

2.局部配置

实际是修改源码,看APIView的源码就知道,默认是parser_classes 为 api_settings.DEFAULT_RENDERER_CLASSES,如图
在这里插入图片描述

而设置parser_classes ,就能让它不读 setting中的配置。
(需要引入from rest_framework.parsers import JSONParser,FormParser 优先级高于全局配置)

  • 情况1:在类中,写parser_classes = [JSONParser,FormParser]
  • 情况2:如果是函数, 就写装饰器 @parser_classes([JSONParser])

特点3:使用Response返回(配置渲染器)

使用from rest_framework.response import Response ,代替JsonResponse,它支持返回渲染多种格式的数据。
需要配置:DEFAULT_RENDERER_CLASSES
默认有两种:

  • 一种是返回json格式
  • 一种是页面的形式
    在这里插入图片描述
    在这里插入图片描述

可视化页面的配置登录按钮

1.登录

在外层url中,添加
from rest_framework.documentation import include_docs_urls
 path('api/',include('rest_framework.urls')),

添加侯,这里就有个登录入口
在这里插入图片描述

2.增加格式渲染选择项(配不配置都可以?)

# 在app应用中的url中添加如下代码
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns= format_suffix_patterns(urlpatterns)

在这里插入图片描述

url中的format参数

在这里插入图片描述

定制渲染器_全局配置

可以增加其他的渲染方式,如:yml格式

'DEFAULT_RENDERER_CLASSES': [
    'rest_framework_yaml.renderers.YAMLRenderer',
    # 'rest_framework.renderers.JSONRenderer'
    'rest_framework.renderers.BrowsableAPIRenderer',
]

在这里插入图片描述
yml格式,的解析器,和渲染器,需要安装如下:
在这里插入图片描述

定制渲染骑_局部配置

在这里插入图片描述

APIView的继承类----GenericAPIView

简单使用

自己先查看源码,找到GenericAPIView类,可以发现,它提供了一系列的的方法。

主要:
首先要定义两个类属性 queryset = Noneserializer_class = None

  • get_queryset()方法 是用来获取 querySet查询集。(支持重写,若不重写,它返回的值就是 类属性 queryset )
  • get_serializer_class() 是用来获取序列化器类的。 (支持重写,若不重写,它返回的值就是 类属性 serializer_class )可以 get_serializer_class()(instance=queryset ,data=xx),但一般可以直接get_serializer(instance=queryset ,data=xx)

继承GenericAPIView, 创建类时:
指定类属性 queryset 和 serializer_class。
使用时queryset,和serializer_class 时,用get_queryset() get_serializer_class() 方法
在这里插入图片描述
定义的路由:默认是需要名为pk的, 也可以修改,如下(后期使用视图集,一般就不用改它了)
from rest_framework.generics import GenericAPIView
然后查看源码
如果没有lookup_url_kwarg, 就取 lookup_field 的 ‘pk’,图上的说明有点点问题
在这里插入图片描述
自定义
在这里插入图片描述

搜索排序

【b 和 c】 搜索排序_配置:

b 是关键字搜索过滤(默认为模糊)
c 是用某字段排序
d 是用某个字段来搜索 (默认为精确匹配)

1.setting中全局配置
'DEFAULT_FILTER_BACKENDS': [
                            "rest_framework.filters.SearchFilter",            # 搜索过滤
                            # "rest_framework.filters.OrderingFilter"         #  排序 
                            ],
'SEARCH_PARAM':'search',        # 配置搜索的关键字参数名,默认是search(在rest_framework 中的setting能查看到)
'ORDERING_PARAM': 'ordering',   # 配置排序的参数名,默认是ordering
---------------------------------------------------------------
2.类中局部配置(优先级高于全局):
filter_backends = [
     filters.SearchFilter,
     filters.OrderingFilter ]
     
search_fields = ["name", 'leader']            允许做关键字查询的字段
ordering_fields = ['id','name','leader']      允许进行排序的字段

b.搜索过滤的使用(类似关键字搜索):

源码

它提供了一个方法filter_queryset()

  • 参数为:搜索过滤前的查询集
  • 中间的处理:实际上用到了filter.py中SearchFilter() 的filter_queryset()
  • 返回为:搜索过滤后的查询集
    在这里插入图片描述
简单使用的效果

要使用filter_queryset() ,方法,就可以进行搜索,
用search 参数接收, 就去去筛选 search_fields 中的字段, 如下图是改了 setting中的配置的名称的
在这里插入图片描述

search_fields设置模糊查询

从源码中可以看出,可以设置 =, 还有 ^ 等

  • 支持 以什么开头的查询, 如:search_fields =[“^name”] 这种写法就是name以某个字符串开头的查询 , =name 是精确匹配(源码在rest_framework的filter)
    如:search?=停 就会过滤name为“停”开头的
  • 也能通过关联表的字段来进行查询 search_fields = [“interfaces__name”, ‘leader’] 外键名__关联表的字段

如下:代码可用于搜索排序的练习(主要为下图)
在这里插入图片描述

class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

    filter_backends = [
        filters.SearchFilter,
        filters.OrderingFilter
    ]

    search_fields = ["name", 'leader']
    ordering_fields = ['id','name','leader']

    def get(self,request):
        queryset = self.get_queryset()
        # 使用过滤方法
        filtered_queryset =self.filter_queryset(queryset)
        s = self.get_serializer(instance=filtered_queryset, many=True)           # 方式2
        return Response(s.data )

c. 排序的使用

  • 第一:类中添加 ordering_fields = [‘id’,‘name’,‘leader’] 表示允许这些字段排序
    • 前端传参数 ordering=name (会以name进行排序),
    • 前端传参数 ordering=-name 反着
    • ordering=name,leader(会多重排序)
      在这里插入图片描述

d 第三方的多字段筛选(默认为精准匹配)

使用

使用户能够根据一系列条件来检索数据
(这个可以和默认的过滤一起用的)
安装(官网中的)
pip install django-filter, 然后注册 和全局配置
在这里插入图片描述

使用:
局部配置

# 搜索、排序功能
filter_backends = [
    filters.SearchFilter,
                   filters.OrderingFilter,
                   DjangoFilterBackend    # 这个是原基础上增加的
                   ]

在这里插入图片描述
在这里插入图片描述

可以改成模糊多字段搜索

略 官网:https://django-filter.readthedocs.io/en/stable/guide/usage.html

自定义【模型搜索类】

如下:可以让某个字段是模糊搜索、 效果是啥?重写的那部分?
在这里插入图片描述
在这里插入图片描述
补充:在这里插入图片描述

使用时,局部还要指定filterset_class 指定自定义过滤骑
在这里插入图片描述

分页功能

使用源码中的分页类

  • 第一:配置分页器( 默认为None,如果想分页就这样配置)
 全局配置setting.py 中的REST_FRAMEWORK中
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',   
    'PAGE_SIZE': 1      # 表示每页默认显示1个数据条数  (源碼分页器 、这个才生效)

 局部配置类中进行设置(优先级高于全局)
    from rest_framework.pagination import PageNumberPagination
    pagination_class = PageNumberPagination
  • 第二:使用sefl.paginate_queryset() 来接受 查询集 , 返回的也是查询集
    • 这个方法 会用到 第一步, setting 中的配置, 每页几个
  • 第三: 使用 self.get_paginated_response() 来代替Response()
    • 这样的话,返回的结构不一样

练习的代码在这里

from rest_framework.pagination import PageNumberPagination
class ProjectsView(GenericAPIView):
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

    # 配置【搜索排序】--- rf_django中 默认为空,需要配置才生效
    filter_backends = [filters.SearchFilter,filters.OrderingFilter]

    # 搜索排序的代码
    search_fields = ["name", 'leader']
    ordering_fields = ['id','name','leader']

    # 配置【分页器】-----默认为空需要配置
    pagination_class = PageNumberPagination

    def get(self,request):
        # 支持搜索过滤
        filtered_queryset=self.filter_queryset(self.get_queryset())

        # 表示有分页的东西
        paginated_querySet = self.paginate_queryset(filtered_queryset)
        if paginated_querySet: # 如果有setting中的配置,才有,如果没有就为None了
            s = self.get_serializer(instance=paginated_querySet,many=True)
            return self.get_paginated_response(s.data)

        s = self.get_serializer(instance=filtered_queryset,many=True)
        return Response(s.data,status=status.HTTP_200_OK)

没有走分页的代码
在这里插入图片描述

走了分页的地方在这里插入图片描述

自定义分页器:

一、自己写一个py文件

a.定义分页类:指定 page_size参数,和每页最大数,
实际上:就是重写 rest_framework 中 的pagination.py 中的PageNumberPagination 类
建议存的位置:

  • 重写时,把这块代码复制出来,可以当道utils包中新建一个 pagination.py, 然后把代码放进来
  • 做修改,自定类继承PageNumberPagination类:

from rest_framework.pagination import PageNumberPagination as _PageNumberPagination (名字换一下,自自定义类就还可以用原来的名字)
在这里插入图片描述
在这里插入图片描述

from rest_framework.pagination import PageNumberPagination as  _PageNumberPagination
class PageNumberPagination(_PageNumberPagination):
    page_size = 10

    page_query_param = 'page'
    page_query_description = '获取的页码'


    page_size_query_param = "page_size"
    page_size_query_description = '每一页数据条数'


    max_page_size = 100
    invalid_page_message = '无效页码'
 

b.修改 get_paginated_response()
它就在PageNumberPagination里面,所以也是可以修改的
在这里插入图片描述
在这里插入图片描述

    def get_paginated_response(self, data):
        response = super().get_paginated_response(data)

        # 添加返回的字段
        response.data['current_page_num'] = self.page.number            # 当前页
        response.data['total_pages'] = self.page.paginator.num_pages    # 总页面数

        # 删除、修改原有字段
        response.data.pop('count')
        # response.data.pop('next')
        # response.data.pop('previous')
        response.data['new_count']=self.page.paginator.count        # 换名字

        # 或者直接使用data参数,来像 父亲方法一样,自己来重写定义
        # response = Response(data)       # data是   列表套字典

        # 再次返回
        return response

或者这样写(这里可以发现,源码实际上用的就是Response 响应 )

# 重写,只返回count,和results, 增加当前页,和最大页
def get_paginated_response(self, data):
    response = Response({
        'count':self.page.paginator.count,
        # 'next': self.get_next_link(),
        # 'previous': self.get_previous_link(),
        'results':data
    })
    # 修改
    response.data['current_num'] =self.page.number     # 添加一个current_num 参数
    response.data['max_page']=self.page.paginator.num_pages

    # 再次返回
    return response
二、使用自定义分页类:

同样,可以全局配置,或者局部配置

全局配置:
'DEFAULT_PAGINATION_CLASS': 'utils.pagination.PageNumberPagination',
局部配置:
from utils.pagination import PageNumberPagination
pagination_class = PageNumberPagination

在这里插入图片描述

GenericAPIView扩展的两种方向

使用GenericAPIView就已经可以完成增删改查的 的接口封装了,如下

  • 查询列表
  • 新增
  • 查询一个
  • 更新一个
  • 删除一个
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Projects,Interfaces
from .serializers import ProjectsModelSerializer
from rest_framework import status,filters
from rest_framework import mixins
# mixins.ListModelMixin,

class ProjectsView(GenericAPIView):
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer
    search_fields = ["name", 'leader']
    ordering_fields = ['id','name','leader']

    def get(self,request):
        # 支持搜索过滤
        filtered_queryset = self.filter_queryset(self.get_queryset())
        # 表示有分页的东西
        paginated_querySet = self.paginate_queryset(filtered_queryset)
        if paginated_querySet:  # 如果有setting中的配置,才有,如果没有就为None了
            s = self.get_serializer(instance=paginated_querySet, many=True)
            return self.get_paginated_response(s.data)

        s = self.get_serializer(instance=filtered_queryset, many=True)
        return Response(s.data, status=status.HTTP_200_OK)

    #
    # def get(self, request, *args, **kwargs):
    #     return self.list(request, *args, **kwargs)

    def post(self,request):
        s = self.get_serializer(data=request.data)
        s.is_valid(raise_exception=True)
        s.save()
        return Response(s.data,status=status.HTTP_201_CREATED)


class ProjectsDetailView(GenericAPIView):
    # def get_object(self,pk):
    #     try:
    #         project_data = Projects.objects.get(id=pk)
    #         return project_data
    #     except Exception as e:
    #         return Response({"msg":'参数有误'},status=400)

    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer
    def get(self,request,pk):
        try:
            project_data = self.get_queryset().get(id=pk)
        except Exception as e:
            return Response({"msg": '参数有误'}, status=400)
        s = self.get_serializer(instance=project_data)
        return Response(s.data)

    def put(self,request,pk):
        try:
            project_data = self.queryset.get(id=pk)
        except Exception as e:
            return Response({"msg": '参数有误'}, status=400)
        s = self.serializer_class(instance=project_data,data=request.data)
        s.is_valid(raise_exception=True)
        s.save()
        return Response(s.data,status=status.HTTP_201_CREATED)

    def delete(self,reuest,pk):
        try:
            project_data = self.queryset.get(id=pk)
        except Exception as e:
            return Response({"msg": '参数有误'}, status=400)
        project_data.delete()
        return Response( {"msg": '删除成功'},status=status.HTTP_201_CREATED)


首先要知道,mixins.py(它抽离了增删改查的方法),什么意思看下面:
上面的代码中,可以发现:get, post ,get ,put delete 方法 和模型、无关,可以把它们抽离处理,restframework已经把这个抽离工作做好了


from rest_framework.generics import GenericAPIView ,点generics 可以进入到源码的地方
mixins.py, 代码中:

  • CreateModelMixin 中有create方法
  • ListModelMixin 中有list方法
  • RetrieveModelMixin 中有retrieve 方法
  • UpdateModelMixin 中有update方法和 partial_update方法
  • DestroyModelMixin 中有destroy方法

在这里插入图片描述

继续改造代码
见下图。继承ListModelMixin,+ GenericAPIView
这样后代码中就不用 再定义 def list()方法了,因为父类ListModelMixin 已经有了
可以发现,视图类中的代码更加简洁 :
在这里插入图片描述

A:一种方向的升级:各种通用视图View

就是把 Mixin 和 genericAPIView 一起结合来继承
在rest_framework 的 generics.py 再次优化了代码, 定义了一些类,继承了 genericAPIView , 和 mixins的 增删改查
rest_framework中的 generics.py文件中
在这里插入图片描述

from rest_framework.generics import GenericAPIView, ListCreateAPIView  

代码又可以简化成如下这种,能实现增删改查
在这里插入图片描述

特点:

  • url中定义要加 as_view(), 它作为的是类视图 (以下第二种,as_view()中是要加字典{})

B:另一种方向的升级:各种视图集 Set

因为:列表和新增不需要id, 查询和更新需要id
ModelViewSet(6个接口)、ReadOnlyModelViewSet(2个接口)
(后面只是说明是B方向怎么来的)

(由来) B 1

from rest_framework.viewsets import ViewSet 点击查看源码 ,然后点找到ViewSetMixin
他提供了一种配置url的方式 as_view(),括号里写字典
as_view({‘get’: ‘list’, ‘post’: ‘create’}) 一项为:请求方法: 具体的调用方法

当使用get, 就执行list方法
如下图,配置url 时, 如果是 ViewSet 的子类 ,as_view(), 里面就是加字典 ,实际上是ViewSetMixin 提供的功能
在这里插入图片描述
以下代码可以验证此功能:,”根据请求路径 和 请求方法,来指定运行(一个是视图集类中的)某个方法

url中:
path('projects/', views.ProjectViewSet.as_view({
    "get":"list_11",
    "post":'create'
})),
path('projects/<int:pk>/', views.ProjectViewSet.as_view({
    'get':"retrieve",
    "put":"update",
    "patch":"partial_update",
    "delete":"destroy"
})),


view中
from rest_framework import viewsets
class ProjectViewSet(viewsets.ViewSet):
    def list_11(self,request,*args,**kwargs):     # 方法名随意和url对上就行
        pass
    def create(self,request,*args,**kwargs):
        pass

    def retrieve(self,request,*args,**kwargs):
        pass
    def update(self,request,*args,**kwargs):
        pass
    def partial_update(self,request,*args,**kwargs):
        pass

    def destroy(self,request,*args,**kwargs):
        pass

(由来) B 2 ViewSet(B1 和 APIVIew 结合)

class ViewSet(ViewSetMixin, views.APIView):

  • 可以实现:这两个一组合 就有了ViewSet , 可以使用APIView的解析器和渲染器了, 又能配置url
  • 但还需要手动定义 list create 等方法,
  • 没怎么用到了,因为B3都比它好

(由来) B 3 GenericViewSet(B1 和GenericAPIView结合)

class GenericViewSet(ViewSetMixin, generics.GenericAPIView):

  • 可以实现更多:它拥有GenericAPIView 搜索、排序、分页功能,并需要 给querySet 和 serializer_class
  • 但还需要手动定义 list create 等方法,

(最终) B4 ModelViewSet ( B3 和 mixin.py 文件结合)

  • 可以实现:利用Mixin提供的方法,就不需要手动去定义 list create方法了
A: 两个接口的,

实际上是 RetrieveModelMixin 里的 已经有了 retrieve()ListModelMixin里,已经有了 list()

class ReadOnlyModelViewSet(
				mixins.RetrieveModelMixin,
                mixins.ListModelMixin,
                           GenericViewSet):
B.六个接口的
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
C. *个接口(灵活使用)

假加,只想要 列表接口,更新接口, 把ModelViewSet超进来,保留想要的也行


from rest_framework import viewsets
class ProjectViewSet(mixins.ListModelMixin,
                     mixins.UpdateModelMixin,
                     viewsets.GenericViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

继承ModelViewSet的,代码基本上是这样写的

最后的代码:

from .models import Projects,Interfaces
from .serializers import ProjectsModelSerializer
from rest_framework import status,filters

from utils.pagination import PageNumberPagination
from rest_framework.viewsets import ModelViewSet
class ProjectViewSet(ModelViewSet):
    queryset = Projects.objects.all()
    serializer_class = ProjectsModelSerializer

    # 搜索、排序功能
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ["name", 'leader']
    ordering_fields = ['id', 'name', 'leader']

    # 分页功能
    pagination_class = PageNumberPagination

自定action(自定义接口)

除了以上的继承了mixins的几个类,提供的list等方法, 还可以自己定义action (方法) ,完成特定的需求。

情况1. 同list,不要需要传id的情况 如: projects/name ,

返回中,项目列表中每一项 只有 id 和name
在这里插入图片描述

情况2. 同查询,需要传id的。

使用get_object 就能知道传的id是啥。路由中就要定义id
如图,请求时路由里有个id。
在这里插入图片描述
也可以写的简单一点,如下
在这里插入图片描述

路由器对象,可以快速定义

作用:快速定义视图集的路由(可以自动生成路由条目,针对模型的增删改查)
在这里插入图片描述
上面的红框,可以使用如下代码代替

from rest_framework import routers
# 1.创建
# router = routers.SimpleRouter()
router = routers.DefaultRouter()            # 相比使用SimpleRouter,它的根路径可以看见
# 2.注册,指定路由前缀, 指定视图集类
router.register(r'projects',views.ProjectViewSet)
urlpatterns = []

urlpatterns +=router.urls

以上代码的作用实际上是 设置了一个 路由前缀, 去 匹配一个 模型视图集类。 如继承的是ModelViewSet。
那么就有6个接口, 如下:
在这里插入图片描述

自定义action,还是自己处理

但是names,路由,和 /interfaces/ 路由,需要

方式1 :还是自己定义
from rest_framework import routers
# 1.创建
# router = routers.SimpleRouter()
router = routers.DefaultRouter()            # 相比使用SimpleRouter,它的根路径可以看见
# 2.注册,指定路由前缀, 指定视图集类
router.register(r'projects',views.ProjectViewSet)
urlpatterns = [
    path('projects/names/',views.ProjectViewSet.as_view({
    'get':'names'
})),
path('projects/interfaces/<int:tk>/', views.ProjectViewSet.as_view({
    'get': 'interfaces'
}))
]

urlpatterns +=router.urls

补充:如果是DefaultRouter,而不是SimpleRouter,根路径就是可以访问的
在这里插入图片描述

方式2:定义方法时加装饰器

from rest_framework.decorators import action

  • detal 必须要指定,表示是否要传pk值
  • methods,表示请求方法,默认为get
  • url_path为 路由,默认为“方法名小写”

(注:如果detail为True, pk是在前面,url_path是在后面的)
在这里插入图片描述

;