一、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