首页 > 其他分享 >drf day03 ApiView、Request、结合Response、反序列化组件编写5个接口

drf day03 ApiView、Request、结合Response、反序列化组件编写5个接口

时间:2023-02-01 19:56:53浏览次数:53  
标签:return ser day03 ApiView self request 序列化 data

一、APIView执行流程(较难)

1.前戏

​ 这个是drf提供的,以后我们写视图中的类都继承这个apiview

​ rest_framework很规范,需要导啥先点一下,然后后面就可以按开头大写导

导入一下
from rest_framework.views import View,APIView

因为APIView继承了View,所以如果用APIView+Jsonresponse 写接口还是和以前一样


如果用APIView+reponse
先导一下
from rest_framework.response import Response

最后返回JSON数据时,可以不用指定safe=False,因为Response可以序列化字典和列表

2.执行流程

1.分析路径,匹配成功后执行了什么
	views.BookView.as_view >>> APIView.as_view
2.APIView中找到了as_view,看一下,发现没干啥
	view = super().as_view(**initkwargs)  >>> 就只是调用了父类的as_view方法
3.as_view最后返回了 csrf_exempt(view)
	装饰器的基本原理
    def auth():
        pass
    def add():
        pass
    假如现在要拿auth来装饰add,用语法糖
    @auth
    def add()   >>> add=auth(add)
    
4.所以可以得知, 继承APIView所写的类,都自动排除了csrf认证
5.APIView.as_view 就变为了 >>>   csrf_exempt(view)(request)
6.又变为了self.dispatch ,但是是找到了ApiView的dispatch
7.研究ApiView.dispatch 发现,request传进来后,被搞了一下
	request = self.initialize_request(request, *args, **kwargs)
     self.request = request
  现在request就变成了新的request,老的request被放在Request里面
		self._request = request
8.从此以后,request就变为新的request了
	往下看,和以前一模一样的,发现有三大认证(未学)和异常捕获
    
    
# 总结
1 去除了所有的csrf
2 包装了新的request,以后在视图类中用的request是新的request  Request类的对象,不是原生的了
-原生的在:新的requets._request
3 在执行视图类的方法之前,执行了3大认证
4 如果在3大认证或视图函数方法执行过程中出了错,会有异常捕获----》全局异常捕获
5 以后视图类方法中的request都是新的了

二、Request对象源码分析(较难)

1.找Request源码,看到左边第一个就是__getattr__   >>>面向对象魔法方法
	该方法 对象.属性,如果属性不存在,就触发执行
2.    def __getattr__(self, attr):
        try:
            return getattr(self._request, attr)
        except AttributeError:
            return self.__getattribute__(attr)
  研究发现,通过反射,完全模仿了老request,老的有啥属性,新的就有啥      
 
3.继续找Request源码,去看data
	发现是一个property伪装装饰器装饰着,意思就是request.date就在执行request.date()
4.以后无论post,put...放在body中提交的数据,都可以用request.date来取,取出来就是一个字典

5.继续找Request源码,去看query_params (查询参数),发现就是老request.GET
6.继续找Request源码,去看FILES ,一样的,多了点功能,今天先不研究多的功能


#总结
-1  新的request用起来,跟之前一模一样,因为新的取不到,会取老的__getattr__
-2 request.data  无论什么编码,什么请求方式,只要是body中的数据,就从这里取,字典
-3 request.query_params 就是原来的request._request.GET
-4 上传的文件从request.FILES
	

三、序列化器介绍和快速使用(不难,重要)

drf提供了两个类,序列化

​ Serializer

​ Modelserializer

以后我们只需要写自己的类,继承这两个类,使用其中的某些方法

具体使用
1.序列化多条(整体)

写一个新的Py文件,写序列化类,导一下serializers
开始写自己的类,继承一下serializers.Serializer,开始写要序列化的字典的字段,大致一一对应模型层中的表,不用加max=之类的

写好了在视图层导一下,然后产生一个序列化对象(要传参)
传参内容:instance——要序列化的数据,一般是QS对象
		many————如果传QS组(多条),一定要写成True,默认是False
    
开始序列化
序列化对象.date 传给前端即可


2.序列化单条——比如说查一本书
写个新路由,用转换器传参,记得带/
写个新视图函数,取出单条直接序列化
	这里有个小技巧,写get方法时,(self,request,*args,**kwargs)
	转换器是关键字传参,**kwargs接收到了,后面取出来即可

    

四、基于序列化器序列化和反序列化

3.反序列化
	反序列化的新增
    序列化对象要新增一个参数,date = request.date 
    校验是否有东西传过来了用is_valid()
    如果有东西过来,要保存
    	回到序列化Py那个文件,写create方法,这里打印一下validated_date看看
        直接用ORM语句保存,可以**validated_date一次性搞定
        返回新增的对象
    直接用序列化对象.save()保存——会自动触发咱们写的create方法    
    
4.反序列化的修改
	视图中还是差不多
    序列化Py中要加一个update方法,instance是要修改的对象,直接拿date数据,然后instance.save()保存
   		记得返回对象

5.删除就太简单了

五、反序列化的校验

​ 类似forms组件

​ 需要导一下先

from rest_framework.exceptions import ValidationError
局部钩子
	抛异常

# 反序列化校验的局部钩子 ,名字不能以sb开头
def validate_name(self, name):
# 校验name是否合法
	if name.startswith('sb'):
# 校验不通过,抛异常
		raise ValidationError('不能以sb开头')
    else:
		return name    

全局钩子
	抛异常

def validate(self, attrs):
    # 校验过后的数据,书名跟出版社名字不能一致
    if attrs.get('name') == attrs.get('publish'):
        raise ValidationError('书名跟出版社名字不能一致')
        else:
            return attrs

六、Drf整体内容

# 1 入门规范
	-web开发模式
    -api接口
    -接口测试工具
    -restful规范
    -序列化反序列化
    -drf快速使用
    -APIView,Request类
    -drf把django的好多东西都重写了
# 2 序列化组件(重要)
	-基本序列化类
    -模型类序列化类
    -如何序列化
    -如何反序列化
    -反序列化的数据校验功能
    
# 3 请求与响应
    -drf的request已经不是原来djagno的request了
    -指定可以接收请求的编码方式
    -指定响应格式
    
    
# 4 视图组件(重点)   View
	-两个视图基类
    -5个视图扩展类
    -9个视图子类
    -视图集
    
    
# 5 路由
	-自动生成路由
    
# 6 认证(登录认证),权限,频率 (重点)

# 7 过滤,排序,分页(次重点)

# 8 自动生成接口文档
----------------------
# 9 JWT 登录认证的,区别与cookie和session,主流
# 10 后台管理美化(django原生的很丑,simpleui二次开发)
# 11 基于角色的访问控制,权限的控制
今日犯错的地方:
	1.request.data拼写成了date。。。
    2.Response(ser) 没有ser.date
    3.钩子函数勾出去忘记给回去了
    4.修改函数时,忘记先拿到要改的对象,忘记拿了!拿了再反序列化
  • 补充

    1.pycharm 点击这个勾上可以显示退一步和进一步的快捷

​ 2.回忆,有名分组,无名分组,位置参数,关键字参数

​ 3.转换器是关键字传参,**kwargs接收到了

​ 4.是name.startswith() 而不是name.startwith()

七、今日代码

urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('author/', views.AuthorView.as_view()),
    path('author/<int:pk>/', views.AuthorOtherView.as_view()),

]

models.py

class Author(models.Model):
    name = models.CharField(max_length=32)
    phone = models.CharField(max_length=32)
    sex = models.CharField(max_length=8)

ser.py

from .models import Author
from rest_framework import serializers
from rest_framework.exceptions import ValidationError


class Authorserializers(serializers.Serializer):
    name = serializers.CharField()
    phone = serializers.CharField()
    sex = serializers.CharField()

    def create(self, validated_data):
        author_obj = Author.objects.create(**validated_data)

        return author_obj

    def update(self, instance, validated_data):
        instance.name = validated_data.get('name')
        instance.phone = validated_data.get('phone')
        instance.sex = validated_data.get('sex')
        instance.save()

        return instance

    def validate_name(self, name):
        if name.startswith('zzz'):
            raise ValidationError('姓名不能以zzz开头')
        return name

    def validate_phone(self, phone):
        if not phone.isdigit():
            raise ValidationError('手机号必须是纯数字')
        return phone

    def validate_sex(self, sex):
        sex_list = ['男', '女']
        if sex not in sex_list:
            raise ValidationError('性别只有男女!')
        return sex

    def validate(self, attrs):
        print(attrs)
        if len(attrs) < 3:
            return ValidationError('字段不足,请补全字段')
        return attrs

views.py

from django.shortcuts import render
from .models import Author
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.views import APIView
from .ser import Authorserializers


# Create your views here.


class AuthorView(APIView):
    def get(self, request):
        author = Author.objects.all()

        ser = Authorserializers(instance=author, many=True)

        return Response(ser.data)

    def post(self, request):
        ser = Authorserializers(data=request.data)
        print(ser)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '创建成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors, 'result': ser.data})


class AuthorOtherView(APIView):
    def get(self, request, *args, **kwargs):
        author = Author.objects.filter(pk=kwargs.get('pk')).first()
        if author:
            ser = Authorserializers(instance=author)
            return Response(ser.data)
        else:
            return Response({'code': 101, 'msg': '查询的内容不存在'})

    def put(self,request, *args, **kwargs):
        author = Author.objects.filter(pk=kwargs.get('pk')).first()
        ser = Authorserializers(data=request.data,instance=author)
        if ser.is_valid():
            ser.save()
            return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
        else:
            return Response({'code': 101, 'msg': ser.errors, 'result': ser.data})

标签:return,ser,day03,ApiView,self,request,序列化,data
From: https://www.cnblogs.com/wznn125ml/p/17083987.html

相关文章