DRF路由组件

 一、路由介绍(Routers)

1.router 的作用

对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息

2.REST framework 提供的两个 router

  • SimpleRouter (简单的路由) (两条)
  • DefaultRouter (默认的路由) (六条)

3.三种路由写法

- path('test/', views.Test.as_view()),
- path('test/', views.Test.as_view({'get':'send_email'})),
- 自动生成路由

二、使用方法

1.使用步骤

前提 : 必须是继承了 ViewSetMixin 类的视图+9种视图子类才可以使用路由组件快速生成路由

  1. 导入路由类 : from rest_framework.routers import SimpleRouter,DefaultRouter

  2. 实例化得到对象 : router = SimpleRouter()

  3. 注册路由 : router.register('book2',views.BookView,'book2')

  4. 把自动生成的路由加到 urlpatterns 中去 : urlpatterns += router.urls

2.参数介绍及注意点

  • register方法参数
# 查看其源码
def register(self, prefix, viewset, basename=None):
    ...
# prefix : 路径,不要带/
# viewset : 视图集
# basename : 路由别名,一般跟路径相同

例:router.register('book2',views.BookView, 'book2') 

 

3.实例

  • models.py
from django.contrib.auth.models import AbstractUser

class base(models.Model):
    name = models.CharField(max_length=16)
    price = models.IntegerField()
    class Mate:
        abstract = True  # 声明这张表是张抽象表,不会在数据库中进行创建,只用来给别的模型类继承

class Book2(base):  # 继承了base,就会有base中的字段
    nid = models.AutoField(primary_key=True)
    author = models.CharField(max_length=16, null=True)
    publish = models.CharField(max_length=16, null=True)

abstract:一般用于多个模型类中存在相同的字段,为了减少代码量和重复写相同的字段, 可以使用abstract 指定一张抽象表用作继承

  • serializers.py
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book2
        fields = "__all__"
  • views.py
from rest_framework.viewsets import ModelViewSet
from mydrf.serializers import BookSerializer

class BookView(ModelViewSet):
    queryset = models.Book2.objects.all()
    serializer_class = BookSerializer
  • urls.py
# 1.导入路由类
from rest_framework.routers import SimpleRouter,DefaultRouter
# 2.实例化得到对象
router = SimpleRouter()
# 3.注册路由
router.register('book2',views.BookView,'book2')
print(router.urls)  # 自动生成的路由
'''
[<URLPattern '^book2/$' [name='book2']>, <URLPattern '^book2/(?P<pk>[^/.]+)/$' [name='book2-detail']>]
'''
	
urlpatterns = []

# 4.把自动生成的路由加到 urlpatterns 中去(实际上就是两个列表相加)
urlpatterns += router.urls
 
  • 查看 SimpleRouter 自动生成的路由(两条)

image-20210415213713208

  • 查看 SimpleRouter 自动生成的路由(六条)(有根,可以通过根访问)

image-20210415213847891

三.添加路由的另一种方式

  • urls.py 文件
# 前三步跟第一种方式一样

# 第四步:导入 include
from django.urls import path,include
# 第五步:自动生成路由 urlpatterns = [ path(r'',include(router.urls)) ] # 可以添加前缀 urlpatterns = [ path(r'app1/',include(router.urls)) ]

image-20210415215744053

四、自动生成路由的底层原理

本质是自动做映射。能够自动成的前提是,视图类中要有 5个方法的某一个或多个
  get--->list
  get---->retrieve
  put---->update
  post---->create
  delete---->destroy

  • ModelViewSet,ReadOnlyModelViewSet可以自动生成
  • 9个视图子类+配合ViewSetMixin 才可以自动生成
  • GenericAPIView+5个视图扩展类+配合ViewSetMixin 才能自动生成

五、action装饰器的使用

导入:

from rest_framework.decorators import action

1.作用

  • 为我们在视图集中自定义的方法生成路由
class BookView(ModelViewSet):
    queryset = models.Book2.objects.all()
    serializer_class = BookSerializer

    # 自定义的方法不会自动生成路由, 需要添加 action 装饰器
    def index(self, request):
        return Response('ok!')

    # 不会自动生成路由
    def top5(self, request):
        return Response('get_5_ok!')

2.action 的参数说明

  • method : 声明该 action 对应的请求方式, 使用列表传递
# 查看其源码 :
    methods = ['get'] if (methods is None) else methods
    methods = [method.lower() for method in methods]

    # 第一条如果没有指定该参数,默认是 "get" 方法
    # 第二条表示方法可以大小写,它都会将其转换成小写

 

  • detail : 声明该 action 的路径是否与单一资源对应,布尔值
 # True : 表示带id的资源路径(可以用来匹配一条数据) : 
        例:127.0.0.1:8000/<pk>/[action方法名]/
 # False : 表示不带id的资源路径(可以匹配多条数据) : 
        例:127.0.0.1:8000/[action方法名]/

 

  • url_path:生成send后路径的名字,默认以方法名命名
  • url_name:别名,反向解析使用,了解即可

3.action 装饰器的使用

  • urls.py
# 导入
from rest_framework.routers import SimpleRouter
# 实例化一个对象
router = SimpleRouter()
# 注册
router.register('send',views.SendView,'send')
#导入include
from django.urls import path,include
# 自动生成路由
urlpatterns = [
    path(r'api/v1/',include(router.urls))
]
  • view,py
# 先导入action
from rest_framework.decorators import action

class SendView(ViewSet):
    @action(methods=['post'],detail=False,url_path='',url_name='send_msg')
    def send_msg(self,request):
        phone = request.query_params.get('phone')
        print('发送成功:%s' % phone)
        return Response({'code':100,'msg':'发送成功'})

 当detail设为True的时候

# 先导入action
from rest_framework.decorators import action

class SendView(ViewSet):
    @action(methods=['post'],detail=True,url_path='',url_name='send_msg')
    def send_msg(self,request,pk):    # 要加上pk参数
        phone = request.query_params.get('phone')
        print('发送成功:%s' % phone)
        return Response({'code':100,'msg':'发送成功'})

 

 

posted @ 2023-02-06 17:35  莫~慌  阅读(73)  评论(0编辑  收藏  举报