5.路由层
【一】视图层源码分析
1)APIView
-
继承了 django 的 view
-
类属性:
-
parser_classes,renderer_classes
-
使用顺序:视图类的,项目配置的,drf内置的
-
-
as_view
和dispatch
-
包装了新的
request
:- 新的
request
对象:request._request
- 视图类的对象:
self.request
就是新的request
- 新的
-
去除了
csrf
认证-
csrf_exempt(view)
-
-
做了三大认证:认证、权限、频率
-
self.perform_authentication(request) self.check_permissions(request) self.check_throttles(request)
-
-
2)GenericAPIView
-
继承了 APIView
-
类属性
-
# 数据源,直接给列表或QuerySet queryset = None # 序列化类 serializer_class = None # get_object指定pk拿参数 lookup_field = 'pk' lookup_url_kwarg = None # 过滤 filter_backends = api_settings.DEFAULT_FILTER_BACKENDS # 分页 pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
-
self.get_queryset()
# 返回self.queryset数据源
def get_queryset(self):
queryset = self.queryset
if isinstance(queryset, QuerySet):
queryset = queryset.all()
return queryset
self.get_serializer(instance=)
# 直接实例化得到序列化类的对象
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs.setdefault('context', self.get_serializer_context())
return serializer_class(*args, **kwargs)
# 可重写,定制序列化与反序列化
def get_serializer_class(self):
return self.serializer_class
- 重写示例
# 序列化用BookModelSerializer,反序列化用BookSerialzier
class BookViewSet(GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
def get_serializer_class(self):
if self.request.method=='GET'
return BookModelSerializer
else:
return BookSerialzier
......
3)5个视图拓展类
# 获取所有
ListModelMixin:list
# 添加
CreateModelMixin:create
# 获取单个
RetrieveModelMixin:retrieve
# 修改
UpdateModelMixin:update
# 删除
DestroyModelMixin:destroy
class CreateModelMixin:
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
# 可重写,用于在保存前后添加功能
def perform_create(self, serializer):
serializer.save()
def get_success_headers(self, data):
try:
return {'Location': str(data[api_settings.URL_FIELD_NAME])}
except (TypeError, KeyError):
return {}
4)9个视图子类
# 获取所有
ListAPIView:
GenericAPIView + ListModelMixin + get方法
# 添加
CreateAPIView:
GenericAPIView + CreateModelMixin + post方法
# 获取单个
RetrieveAPIView:
GenericAPIView + RetrieveModelMixin + get方法
# 修改
UpdateAPIView:
GenericAPIView + UpdateModelMixin + put方法
# 删除
DestroyAPIView:
GenericAPIView + DestroyModelMixin + delete方法
# 获取所有,添加
ListCreateAPIView:
GenericAPIView + ListModelMixin + CreateModelMixin+ get方法+ post方法
# 获取单个,修改,删除
RetrieveUpdateDestroyAPIView:
GenericAPIView + RetrieveModelMixin + UpdateModelMixin + DestroyModelMixin + get方法 + put方法 + delete方法
# 获取单个,修改
RetrieveUpdateAPIView:
GenericAPIView + RetrieveModelMixin + UpdateModelMixin + get方法 + put方法
# 获取单个,删除
RetrieveDestroyAPIView:
GenericAPIView + RetrieveModelMixin + DestroyModelMixin + get方法 + delete方法
5)视图集
# ModelViewSet:5接口
mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet
# ReadOnlyModelViewSet:2接口(只读)
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet
# ViewSet:
ViewSetMixin
APIView
# GenericViewSet:
ViewSetMixin
GenericAPIView
# ViewSetMixin:控制路由写法的类,重写了as_view
# 路由做好映射,可写任意名字的方法
- 路由
path('send_sms',EgView.as_view({'get':'send_sms'})),
- 视图类
class EgView(ViewSetMixin,APIView):
def send_sms(self):
print('发送短信')
return Response({'code':100,'msg':'发送成功'})
【二】路由层
- 只要继承了
ViewSetMixin
D的子类,路由写法改变
from rest_framework.routers import SimpleRouter, DefaultRouter
# 类实例化得到对象
router = DefaultRouter()
# 注册视图类
router.register('book', BookViewSet, basename='book')
# 添加到url
# 方式一
'''
urlpatterns = [path('', include(router.urls))]
'''
# 方式二
urlpatterns = []
urlpatterns += router.urls
1)SimpleRouter
与DefaultRouter
的区别
SimpleRouter
:- 正常页面,没有返回404
DefaultRouter
:- 美化后的页面(配置rest_framework),不会报错,生成一个根
2)action装饰器
- 定义与请求方式不同名的方法
from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
class EgViewSet(ViewSet):
# http://localhost:8000/api/v1/eg/send_sms/
# 发送POST请求触发(列表内可写多条)
@action(methods=['POST'], detail=False)
def send_sms(self, request):
print('发送短信')
return Response({'code': 200, 'msg': '发送成功'})
- action参数就是方法名的字符串
from rest_framework.viewsets import ModelViewSet
class EgBookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
# 重写
def get_serializer_class(self):
if self.action == 'list' or self.action == 'create':
return BookSerializer
elif self.action == 'retrieve' or self.action == 'update' or self.action == 'destory':
return BookModelSerializer
elif self.action == 'login':
return BookModelSerializer
@action(methods=['POST'], detail=False)
def login(self, request, *args, **kwargs):
print('登录')
return Response({'code': 200, 'msg': '登录成功'})
- action参数
# 请求方式,可多个
methods=None
#
# False:api/v1/books/login/
# True:api/v1/books/4/login/
detail=None
# 路径名字,默认方式名
# url_path = abc ——> api/v1/books/abc/
url_path=None
# 反向解析
url_name=None