目录
反序列化类的校验部分源码解析-断言-drf之请求-drf之响应-视图组件介绍及两个视图基类-基于GenericAPIView的五个视图扩展类
昨日内容回顾
# 1 序列化类的常用字段
CharField
IntegerField
DecimalField
DateTimeField
BooleanField
ListField
DictField
# 2 字段参数
-max_length min_length 最大最小长度
-max_value min_value 最大最小值
-required 表明该字段在反序列化时必须输入 默认True
-default 反序列化时使用的默认值
-read_only 只读 write_only 只写
# 3 定制序列化字段(改名字)
-source这个字段参数
-如果是表模型自己的字段 直接写
-如果是关联字段 通过外键拿到
# 4 定制序列化字段(格式更丰富)
-在序列化类中使用:SerializerMethodField 配合一个get_字段名的方法 方法返回什么 这个字段就是什么---> 这种字段以后不能用来做反序列化了
-在表模型中使用 写方法的方式 方法返回什么 这个字段就是什么 序列化类中需要配合ListField DictField---> 这种字段以后不能用来做反序列化了
-方法可以包装成数据属性 也可以不(伪装)
# 5 反序列化校验四层
-1 字段自己的校验规则 序列化类字段参数控制的
-2 每个字段单独设置校验方法(了解)
-3 局部钩子
-4 全局钩子
# 6 ModelSerializer:继承自Serializer
class BookSerializer(ModelSerializer):
# 如果字段是映射过来的,也会把字段属性[反序列化校验规则],也会映射过来,有可能会校验失败,不能写入
# 咱们重写这个字段,不加任何规则,取消掉它(意思就是先使用我们自己写的这个字段规则)
name = serializer.CharField()
class Meta:
model=Author
# fields="__all__"
# 只要是序列化的字段和反序列化的字段,都要在这注册
# 序列化的字段,可能不是表模型的字段,是咱自己写的方法
# 序列化的字段,可能是使用SerializerMethodField,也要注册
fields=['name','photo','gender','addr'...]
extra_kwargs={} # 给字段类增加属性,read_only 和write_only用的多
# 其他表中的字段,只要用到就要在上面注册
gender=serializer.CharField()
addr=serializer.CharField()
局部钩子,全局钩子完全一样
SerializerMethodField也一样
create
update
# 7 反序列化字段 一定要跟表模型的字段是对应的吗?
不一定 随意写
今日内容概要
-
1 反序列化类校验部分源码解析(了解)
-
2 断言
-
3 drf之请求
- 3.1 Request能够解析前端传入的编码格式
- 3.2 Request类有哪些属性和方法
-
4 drf之响应
- 4.1 Response能够响应的编码格式
- 4.2 Response的源码属性和方法
-
5 视图组件介绍及两个视图基类
- 5.1 APIView+ModelSerializer+Response写五个接口
- 5.1.1 视图类
- 5.1.2 序列化类
- 5.1.3 路由
- 5.1 APIView+ModelSerializer+Response写五个接口
-
6 基于GenericAPIView+五个视图扩展类
- 6.1 视图类
- 6.2 序列化类
- 6.3 路由
今日内容详细
1 反序列化类校验部分源码解析(了解)
# 反序列化校验 什么时候开始执行校验
-视图类中执行到 ser.is_valid()就会执行校验 校验通过返回True 不通过返回False
# 入口:ser.is_valid() 是序列化类的对象 假设序列化类是BookSerializer---> 点is_vaild进入源码 找不到 找到父类BaseSerializer中有:
【raise_exception:先注意】
def is_valid(self, *, raise_exception=False):
if not hasattr(self, '_validated_data'):
try:
# self序列化类的对象,属性中没有_validated_data,一定会走这句【核心】
self._validated_data = self.run_validation(self.initial_data)
except ValidationError as exc:
self._validated_data = {}
self._errors = exc.detail
else:
self._errors = {}
if self._errors and raise_exception:
raise ValidationError(self.errors)
return not bool(self._errors)
# self._validated_data = self.run_validation(self.initial_data)
核心---> self序列化类的对象
-切记一定不要按住ctrl键点击
-真正的执行顺序是 从上往下 找不到 再往上
-最终从Serializer类中找到了run_validation 而不是Field中的 run_validation
def run_validation(self, data=empty):
# 字段自己的,validates方法
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data
# 局部钩子----【局部钩子】
value = self.to_internal_value(data)
try:
self.run_validators(value)
# 全局钩子--》如果在BookSerializer中写了validate,优先走它,非常简单
value = self.validate(value)
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
return value
# 局部钩子 self.to_internal_value(date)---> self是BookSerializer的对象 从根上找
def to_internal_value(self, data):
ret = OrderedDict()
errors = OrderedDict()
fields = self._writable_fields
# fields写在序列化类中一个个字段类的对象
for field in fields:
# self BookSerializer的对象,反射validate_name
validate_method = getattr(self, 'validate_' + field.field_name, None)
try:
# 在执行BookSerializer类中的validate_name方法,传入了要校验的数据
validated_value = validate_method(validated_value)
except ValidationError as exc:
errors[field.field_name] = exc.detail
else:
set_value(ret, field.source_attrs, validated_value)
if errors:
raise ValidationError(errors)
return ret
2 断言
# 源码中大量使用try和断言
# 关键字assert 有什么作用 断定你是xx 如果不是就抛异常
name = 'zpf'
if name == 'kjhl':
print('对了')
else:
print('错了') # 错了
raise Exception('名字不是zpf,不能往下走') # Exception: 名字不是zpf,不能往下走
assert name=='zpf' # 断定是 如果不是 就抛异常
3 def之请求
3.1 Request能够解析的前端传入的编码格式
# 需求是该接口只能接收json格式 不能接收其他格式
# 方式一:在继承自APIView及其子类的视图类中配置(局部配置)
# 总共有三个:form rest_framework.parsers import JSONParser,FormParser,MultiPartParser
class BookView(APIView):
parser_classes = [JSONParser,]
# 方式二:在配置文件中配置(影响所有 全局配置)
-django有套默认配置 每个项目有个配置
-drf有套默认配置 每个项目也有个配置---> 就在django的配置文件中
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
],
}
# 方式三:全局配置了1个 某个视图类想要三个 怎么配?
-只需要在视图类 配置3个即可
-因为:先从视图类自身找 找不到 去项目的drf配置中找 再找不到 去drf默认的配置找
3.2 Request类有哪些属性和方法(学过)
# 视图类方法中的request
-data
-__getattr__
-query_params
4 drf之响应
4.1 Response能够响应的编码格式
# drf 是django的一个app 所有需要注册
# drf响应 如果使用浏览器和postman访问同一个接口 返回格式是不一样的
-drf做了个判断 如果是浏览器 好看一点 如果是postman只要json数据
# 方式一:在视图类中写(局部配置)
-两个响应类---> 找---> drf的配置文件中找---> 两个类
-form rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
class BookView(APIView):
renderer_classes=[JSONRenderer,]
# 方式二:在项目配置文件中写(全局配置)
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES':[
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
],
}
# 方式三:使用顺序(一般就用内置的即可)
优先使用视图类中的配置 其次使用项目配置文件中的配置 最后使用内置的
4.2 Response的源码属性或方法
# drf 的Response 源码分析
-from rest_framework.response import Response
-视图类的方法返回时 return Response 走它的__init__ init中可以传什么参数
# Response init可以传的参数
def __init__(self,
data=None,
status=None,
template_name=None,
headers=None,
exception=False,
content_type=None)
-data:之前咱们写的ser.data 可以是字典 列表 字符串---> 序列化后返回给前端---> 前端在响应体中看到的就是这个
-status:http响应的状态码 默认是200 你可以改
-drf在status包下 把所有http响应状态码都写了一遍 常量
-from rest_framework.status import HTTP_200_OK
-Response('dddd', status=status.HTTP_200_OK)
-tempate_name:了解即可 修改响应模板的样子 BrowsableAPIRenderer定死的样子 后期公司可以自己制定
-headers:响应头 http响应的响应头
-原生的django 如何向响应头中加对象
# 四件套 render redirect HttpResponse JsonResponse
obj = HttpResponse('dddd')
obj['xxc'] = 'yyc'
return obj
-content_type:响应编码格式 一般不动
# 重点:data status headers
5 视图组件介绍及两个视图基类
# drf 视图 视图类 学过APIView drf的基类 drf提供的最顶层的类
# APIView跟之前的View区别
-传入到视图方法中的是REST framework的Request对象 而不是Django的HttpRequest对象:
-视图方法可以返回REST framework的Response对象
-任何APIException异常都会被捕获到 并且处理成合适的响应信息
-在进行dispatch()分发前 会对请求进行身份认证 权限检查 流量控制
# 两个视图基类
APIView
-类属性:
renderer_classes # 响应格式
parser_classes # 能够解析的请求格式
authentication_classes # 认证类
throttle_classes # 频率类
permission_classes # 权限类
-基于APIView+ModelSerializer+Response写五个接口
-详见代码
5.1.1 视图类
from .models import Book
from .serializer import BookSerializer
class BookView(APIView):
def get(self, request):
books = Book.objects.all()
ser = BookSerializer(instance=books, many=True)
return Response(ser.data)
def post(self, request):
ser = BookSerializer(data=request.data)
if ser.is_valid():
ser.save()
# 咱们现在只有ser序列化类的对象,但是咱们想要,新增的对象---》序列化成字典---》大前提,序列化类中的create方法一定要返回新增的对象
return Response({'code': 100, 'msg': '新增成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
class BookDetailView(APIView):
def get(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books)
return Response(ser.data)
def put(self, request, pk):
books = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=books, data=request.data)
if ser.is_valid():
ser.save()
return Response({'code': 100, 'msg': '修改成功', 'result': ser.data})
else:
return Response({'code': 101, 'msg': ser.errors})
def delete(self, request, pk):
Book.objects.filter(pk=pk).delete()
return Response({'code': 100, 'msg': '删除成功'})
5.1.2 序列化类
# ModelSerializer的使用
class BookSerializer(serializers.ModelSerializer):
# 跟表有关联
class Meta:
model = Book
field = ['name', 'price', 'publish_detail', 'zuthor_list' 'publish', 'authors']
extra_kwargs = {
'name': {'max_length': 8},
'publish_detail': {'read_only': True},
'author_list': {'read_only': True},
'publish': {'write_only': True},
'authors': {'write_only': True},
}
5.1.3 路由
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', views.BookView.as_view()),
path('books/<int:pk>/', views.BookDetailView.as_view()),
]
6 基于GenericAPIView+5个视图扩展类
6.1 视图类
from rest_framework.mixins import CreateModelMixin, UpdateModelMixin, DestroyModelMixin, RetrieveModelMixin, ListModelMixin
from rest_framework.generics import GenericAPIView
# 基于GenericAPIView+五个视图扩展类写接口
class BookView(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request):
return self.list(request)
def post(self, request):
return self.create(request)
class BookDetailView(GenericAPIView, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
6.2 6.3 序列化类和路由
# 没有变化
标签:self,视图,序列化,data,Response,drf
From: https://www.cnblogs.com/zpf1107/p/17092197.html