5.路由层

【一】视图层源码分析

1)APIView

  • 继承了 django 的 view

  • 类属性:

    • parser_classes,renderer_classes
      
    • 使用顺序:视图类的,项目配置的,drf内置的

  • as_viewdispatch

    • 包装了新的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':'发送成功'})

【二】路由层

  • 只要继承了ViewSetMixinD的子类,路由写法改变
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)SimpleRouterDefaultRouter的区别

  • 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
posted on 2024-08-01 10:39  晓雾-Mist  阅读(14)  评论(0)    收藏  举报