drf之cbv源码、序列化组件、反序列化保存

cbv源码分析

请求来了—》执行 视图类.as_view()(request)—》内部执行了—》View的as_view的内部的view闭包函数—》闭包函数调用了 self.dispatch---->是BookView的,于是去了View的----》通过反射获取跟请求方式同名的方法—》然后执行,把request传入

APIView执行流程分析

  1. 使用drf,以后都写cbv -----> 继承一个视图类 ----> 以后都继承drf提供 的APIView
    导入:from rest_framework.views import APIView

  2. APIView 继承了djagno的View

  3. 这三个都是一个

    from django.views import View
    from django.views.generic import View
    from django.views.generic.base import View
    

继承APIView写cbv

执行起来跟之前效果一样,内部发生了非常大的变化

  1. 写视图类
    from rest_framework.views import APIView
        class PublishView(APIView):
            def get(self, request):
                return JsonResponse({'code': 999})
    
  2. 配置路由
    path('publish/', PublishView.as_view()),
    

APIView的执行流程分析

比之前继承django的View多了如下
0 去除了csrf认证
1 包装了新的request
2 执行了认证,频率,权限 这三大认证
3 全局异常处理:在视图类的方法中执行报错,会被异常捕获,做统一处理

执行流程分析

0去除了csrf认证

请求来了 ----> 执行PublishView.as_view()(request) ----> PublishView类没有as_view ----> 找父类 ----> APIView的as_view ----> 本质在禁用csrf认证

@classmethod
def as_view(cls, **initkwargs):
    # 调用父类的as_view得到返回值赋值给view---》django的View的as_view【看过】---》返回View的as_view的闭包函数 view
    view = super().as_view(**initkwargs)  # 现在这个view就是原来看的View的as_view的view
    # 去除了csrf认证----》局部禁用csrf---》在视图函数上加 装饰器csrf_exempt
    # 加了装饰器的本质:    被装饰的函数=装饰器(被装饰的函数)
    return csrf_exempt(view)
三大认证和重新定义request

PublishView.as_view()(request) ---- > 执行了禁用掉csrf的View的as_view的view — - > self.dispath ----> APIView的dispath

def dispatch(self, request, *args, **kwargs):
	# 1 包装了新的request对象
	request = self.initialize_request(request, *args, **kwargs)
	# 把新的request,赋值给了 self.request
	# self 是 PublishView的对象 
	self.request = request
	try:
	    # 2 执行了3大认证
	    self.initial(request, *args, **kwargs)
	    
	    ######开始### 跟之前View的dispath是一样的---》根据请求方式执行类中同名方法
	    ###执行视图类的方法
	    if request.method.lower() in self.http_method_names:
	        handler = getattr(self, request.method.lower(),
	                          self.http_method_not_allowed)
	    else:
	        handler = self.http_method_not_allowed
	
	    response = handler(request, *args, **kwargs)
	    ######结束###
包装新的request
1 request.data:前端传入的数据(post,put,编码格式)—>写到在请求体中的数据,都用
2 老request中有 request.GET 新的使用request.query_params 充当
3 其他的所有属性方法,用起来跟之前一样

三大认证

self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)

序列化组件介绍

将库中取出的数据序列化
借助于drf提供的序列化组件来完成快速序列化

使用步骤

  1. 先在配置文件中注册

    INSTALLED_APPS = [
            'rest_framework',
            ]
    
  2. 写一个序列化类
    新建一个py文件serializer.py,继承drf提供的serializers.Serializer
    在类中写要序列化的字段:字段类,跟之前学过的models.py中的字段类完全对应,但是比models多

    class BookSerializer(serializers.Serializer):
    	# 需要序列化哪个字段就写哪个
        name = serializers.CharField(max_length=8, min_length=3,required=False)
        price = serializers.IntegerField(required=False)
    
  3. 在视图类中,使用序列化类

# 多条:  
# book是从数据库取出来的对象
ser = BookSerializer(instance=book, many=True)
# 单条:
ser = BookSerializer(instance=book)
  1. 拿到序列化后的数据
    ser.data可能是列表,可能是字典

  2. 使用drf提供的Resposne 返回
    导入:from rest_framework.response import Response
    使用:return Response(ser.data)

序列化组件快速使用之序列化

  1. 路由

    urlpatterns = [
        path('users/', UserView.as_view()),
        path('users/<int:pk>', UserDetailView.as_view()),
    ]
    
  2. 视图类

    from rest_framework.views import APIView
    from app01.models import Book
    from .serializer import BookSerializer
    from rest_framework.response import Response
    
    
    class BookView(APIView):
    	# 之前用for循环,现在用序列化类
        # 传了两个参数:instance 要序列化的对象(qs,单个对象)   many=True表示序列化多条,如果不写就是序列化一条
        def get(self, request):
            book = Book.objects.all()
            ser = BookSerializer(instance=book, many=True)
            # 拿到序列化后的数据  ser.data--->多条就是列表  单条字典
            return Response(ser.data)
    
    class BookDetailView(APIView):
        def get(self, request, pk):
            book = Book.objects.filter(pk=pk).first()
            ser = BookSerializer(instance=book)
            return Response(ser.data)
    
  3. 序列化类

    from rest_framework import serializers
    class BookSerializer(serializers.Serializer):
    	# 写要序列化的字段
    	name = serializers.CharField(max_length=8, min_length=3,required=False)
    	price = serializers.IntegerField(required=False)
    

常用字段类和参数

常用字段类

# 字段类上,可以传参数,是做反序列化校验用的
	CharField:max_length,min_lenght,allow_blank: 可以不传
    IntegerField:max_value,min_value
    
 # 所有字段都可以用通用的
	-非常重要:read_only,write_only
    -default,required,allow_null
参数说明
max_length最大长度
min_lenght最小长度
allow_blank是否允许为空
trim_whitespace是否截断空白字符
max_value最小值
min_value最大值

常用参数

参数名称说明
read_only表明该字段仅用于序列化输出,默认False
write_only表明该字段仅用于反序列化输入,默认False
required表明该字段在反序列化时必须输入,默认True
default反序列化时使用的默认值
allow_null表明该字段是否允许传入None,默认False
validators该字段使用的验证器
error_messages包含错误编号与错误信息的字典
label用于HTML展示API页面时,显示的字段名称
help_text用于HTML展示API页面时,显示的字段帮助提示信息

序列化组件检验

序列化组件

  1. 序列化
  2. 反序列化
  3. 反序列化校验

检验

在视图类中写ser.is_valid(),就会进入序列化类中进行检验

检验有三种方式
1 字段自己的校验规则(字段类的属性上)
2 局部钩子(给某个字段加校验规则)
3 全局钩子

字段自己

在序列化类中,参数就是字段自己约束的

id = serializers.IntegerField(read_only=True)
name = serializers.CharField(required=False)
price = serializers.IntegerField(required=False)
局部钩子
# 写一个方法  validate_字段名,传入要校验的数据--》前端传入的
def validate_name(self, value):
	if value.startswith('sb'):
	    raise ValidationError('不能以sb开头')  # 如果校验失败,抛ValidationError
	return value  # 如果校验通过,返回 value,后续继续用
全局钩子
# 名字和hobby不能一致   多个字段的同时校验
def validate(self, attrs):  # 前端传入的所有数据,校验过后attrs 字典
    name = attrs.get('name')
    hobby = attrs.get('hobby')
    if name == hobby:
        raise ValidationError('名字和爱好不能一样')
    else:
        return attrs

反序列化保存

在视图函数中
def post(self, request):
	# 实例化序列化类并传入前端传来的数据
    ser = BookSerializer(data=request.data)
    if ser.is_valid():
        ser.save()
        return Response({'code': 100, 'msg': '新增成功', 'data': ser.data})
    else:
        return Response({'code': 200, 'msg': ser.errors})
在序列化类中

在序列化类中需要写重写一个create方法

    def create(self, validated_data):  # validated_data:前端传入,校验过后的数据
        user = User.objects.create(**validated_data)
        return user
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值