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种视图子类才可以使用路由组件快速生成路由
-
导入路由类 :
from rest_framework.routers import SimpleRouter,DefaultRouter
-
实例化得到对象 :
router = SimpleRouter()
-
注册路由 :
router.register('book2',views.BookView,'book2')
-
把自动生成的路由加到 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 自动生成的路由(两条)
- 查看 SimpleRouter 自动生成的路由(六条)(有根,可以通过根访问)
三.添加路由的另一种方式
- urls.py 文件
# 前三步跟第一种方式一样
# 第四步:导入 include
from django.urls import path,include
# 第五步:自动生成路由
urlpatterns = [
path(r'',include(router.urls))
]
# 可以添加前缀
urlpatterns = [
path(r'app1/',include(router.urls))
]
四、自动生成路由的底层原理
本质是自动做映射。能够自动成的前提是,视图类中要有 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':'发送成功'})