drf 自动生成路由
drf路由系统
由于继承了ViewSetMinxin类 路由的写法变了,有三种写法。需要学习一下
- 原生写法
path('books/',views.BookView.as_view())
- 继承ViewSetMinxin重写as_view后的写法
path('books/',views.BookView.as_view({'get':'list','post':'create'}))
- 自动生成路由
drf 提供了两个路由类,继承ModelViewSet后路由可以自动生成。
SimpleRouter与DefaultRouter
# 1. 导入路由类
from rest_framework.routers import SimpleRouter,DefaultRouter
# 2. 实例化
"""
两种类的区别
1.SimpleRouter 生成了可以访问的路径
2.DefaultRouter 生成了可以访问的路径和一个根路径(api-root)里面存放了 路径的超链接
"""
router = SimpleRouter()
# router = DefaultRouter()
# 3. 注册
"""第一个参数路径不用带/ ,
第二个参数视图类
第三个参数是别名,一般与路径名相同,"""
router.register('books',views.BookView,'books')
# 4 在urlpatterns中注册 两种方式
urlpatterns = [
path('admin/', admin.site.urls),
]
"""
1. urlpatterns += router.urls
2. path('api/v1/',include(router.urls))
- 可以在路由中添加额外的标识api/vi
"""
urlpatterns += router.urls
from django.urls import path,include # 第二种用的比较多
urlpatterns = [
path('api/v1/',include(router.urls)),
]
自动生成路由的本质
本质就是自动做映射,视图类中要有5个接口方法的几个或更多个(自己编写的)
get--- list
get--- retrieve
put--- update
post--- create
delete--- destory
继承ModelViewSet,ReadOnlyModelViewSet可以自动生成
继承9个视图子类+配合ViewSetMixin 才可以自动生成
继承ViewSetMixin+ GenericAPIView+5个视图扩展类 才能自动生成
GenericViewSet 内部包含了GenericAPIView,ViewSetMixin
" 我们可以直接使用 GenericViewSet+视图扩展类"
action装饰器
注意:不是as_view的actions参数。
可以写在视图类的中,可以自动生成路由
# action装饰器路由编写
# 方式一:手动写
path('send/',views.SendView.as_view({'get':'send_msg'})),
# 方式二:在外面使用register注册,需要在视图函数内使用action装饰器
from rest_framework.routers import SimpleRouter,DefaultRouter
router = SimpleRouter()
router.register('send',views.SendView,'send')
path('api/v1/',include(router.urls)),
视图
基于 ViewSet 编写
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
class SendView(ViewSet):
""" action 参数
methods 指定请求方式传列表,列表内可以填多个
detail 只能传True False
-False 不带id路径 只能生成 send/send_msg/
-True 带id的路径 send/pk/send_msg/ 需要在视图类中添加参数pk
url_path 路径 send/ 后面的名字,默认方法名
url_name 别名反向解析使用"""
@action(methods=['GET','POST'],detail=True,url_path='haha',url_name='send_msg')
def send_msg(self,request,pk):
# query_params 含有路由携带的参数
phone = request.query_params.get('phone')
print(request.query_params)
return Response({'code':100,'msg':'发送成功'})
扩展
# 补充:
-1 不同请求方式可以使用不同序列化类
-2 不同action使用不同序列化类
class SendView(GenericViewSet):
queryset = None
serializer_class = '序列化类'
def get_serializer(self, *args, **kwargs):
if self.action=='lqz':
return '某个序列化类'
else:
return '另一个序列化列'
@action(methods=['GET'], detail=True)
def send_sms(self, request,pk):
print(pk)
phone = request.query_params.get('phone')
print('发送成功,%s' % phone)
return Response({'code': 100, 'msg': '发送成功'})
@action(methods=['GET'], detail=True)
def lqz(self,request): # get
# 序列化类
pass
@action(methods=['GET'], detail=True)
def login(self,request): # get
# 序列化类
pass
测试伪代码
class SendView(GenericViewSet):
queryset = Book.objects.all()
serializer_class = '序列化类'
# 当有多个相同请求的方法,需要重写get_serializer,因此时的action被ViewSetMixin的view映射成了方法名
def get_serializer(self):
if self.action == 'login':
return print('序列化类1')
else:
return print('序列化类2')
@action(methods=['GET'], detail=False)
def send_msg(self, request):
self.get_serializer()
return Response('send_msg')
@action(methods=['GET'],detail=False)
def login(self, request):
self.get_serializer()
return Response('login')
@action(methods=['POST'],detail=False)
def register(self, request):
return Response('register')