WED.序列化类之 Serializer
类中方法和函数的区别
方法
绑定给对象的方法
-
内有任何装饰器
-
对象来调用,会自动传值,把对象当做第一个参数传进来
绑定给类的方法
- 类来调用,会自动传值,把类当做第一个参数传进来
函数
- 通过
@staticmethod
修饰的函数被称为普通函数,也被称为静态方法,有几个值,调用时就传入几个值。
注意
1、对象可以调用类的方法,且仍然会把类作为第一个参数自动传入
2、类也可以调用对象的方法,'但只作为普通函数',不会将对象或类作为第一个参数自动传入
3、方法会自动传参,而函数有几个值就传几个值
4、方法不一定是方法,得看是谁来调用
DRF 中 APIView 的执行流程
1、APIView 中的 as_view 代码
view = super().as_view(**initkwargs)
return csrf_exempt(view)
2、view 内部本质执行了 self.dispatch()
- 执行了 APIView 的 dispatch
-- request = self.initialize_request(request, *args, **kwargs)
--self.initial(request, *args, **kwargs)
3、处理了异常(包含三大认证和视图类中的方法)
DRF的Request类的对象
只要继承了 APIView,后续的视图类中使用的 request 对象,都是 DRF 的 Request 类的对象
1、但是用起来,跟之前 Django 的一样
2、request.data, post 和 put 提交的数据,都会在里面,字典形式
- urlencoded编码 --> request.data 是 QueryDict 的对象
- formdata编码 --> request.data 是 QueryDict 的对象
- json编码 --> request.data 是 dict
- request.query_params --> 它就是原来的request.GET, 即 self._request.GET
鸭子类型
-
Python 中不需要父类或接口来约束子类,而子类中有这个方法即称为鸭子类型
-
Python 推崇人为约束,即程序员自行约束
-
但鸭子类型存在风险,若不通过约束,则可能存在方法不同名无法调用的情况
序列化类之Serializer
序列化类常用字段
# 重点的:
'''
CharField
IntegerField
DecimalField
DateTimeField
DateField
ListField
DictField
'''
# 其他还有很多但的忽略
序列化类常用字段参数
# 通用的
read_only 表明该字段仅用于序列化输出,默认 False(重点)
write_only 表明该字段仅用于反序列化输入,默认 False(重点)
required 表明该字段在反序列化时必须输入,默认 True(了解)
default 反序列化时使用的默认值(了解)
allow_null 表明该字段是否允许传入 None,默认 False(了解)
validators 该字段使用的验证器(写函数的列表,使用这些函数校验该字段)(了解)
error_messages 包含错误编号与错误信息的字典
# 其他的
# CharField
max_length 最大长度
min_lenght 最小长度
allow_blank 是否允许为空
trim_whitespace 是否截断空白字符
# IntegerField
max_value 最小值
min_value 最大值
反序列化(重写 Create 和 Update)
# 重点:
-如果想序列化和反序列化都用一个序列化类,可以使用如下俩字段控制
-read_only 表明该字段仅用于序列化输出,默认 False(重点)
-write_only 表明该字段仅用于反序列化输入,默认 False(重点)
-如果写起来比较麻烦,可以使用两个序列化类,一个序列化,一个反序列化
# source 的用法
name1 = serializers.CharField(source='name')--->意思是name1映射成models中的name
# 如果继承 Serializer 类,要修改和保存,一定要重写 update 和 create
BookSerializer---》Serializer---》BaseSerializer--save的核心代码
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
else:
self.instance = self.create(validated_data)
SerializerMethodField 的使用
class BookSerializer(serializers.Serializer):
price = serializers.IntegerField()
name = serializers.CharField()
# publish = serializers.CharField()
# 显示出版社的详情
## 方式一(在序列化类中写)
publish_name = serializers.SerializerMethodField(read_only=True) # 只能用来做序列化
def get_publish_name(self,obj):
# obj 就是当前要序列化的book对象
return obj.publish.name
return {'name':obj.publish.name,'addr':obj.publish.addr}
# 方式二(在模型类中写方法,方法返回什么,这个字段就是什么)(在表模型中写用的多)
publish_detail=serializers.CharField()
publish_detail=serializers.DictField()
## 方式三
publish_detail = serializers.CharField(source='publish.addr')
序列化类之 ModelSerializer
from .models import Book, Publish
class PublishModelSerializer(serializers.ModelSerializer):
# # 指定跟表的对应关系
class Meta:
model = Publish # 跟哪个表有关系
# fields =['name','addr']
# fields ='__all__' # 所有字段,只序列化字段,不序列化方法
fields = ['name', 'addr', 'name_detail']
# 给字段类,传递参数、属性
extra_kwargs={
'addr':{'max_length':8,'min_length':3,'write_only':True},
'name':{'write_only':True}
# }
# # 不重要的
exclude=['name'] '它跟 fields 只能有一个'
# depth=1 返回其下所属全部字段,不能只返回其中个别字段
#1 不用重写 create 和 update
#2 在出版社名字后加 _vip
# 方式一
# name=serializers.SerializerMethodField()
# def get_name(self,obj):
# return obj.name+'_vip'
# 方式二,在表模型中定义一个name_detail,在fields中写一些字段或方法
# 序列化的时候使用 name_detail,反序列化的时候使用 name
# name_detail = serializers.CharField(read_only=True) 如果是个方法,这句可以不写
# name = serializers.CharField(write_only=True)
#3 限制addr,最大长度8,最小长度3
序列化类全局,局部钩子
# 局部钩子:给某个字段再增加校验(固定用法),定义一个方法,名字为 validate_ 字段名
def validate_addr(self, item):
if item.startswith('sb'):
# 抛异常,不能以 sb 开头
raise ValidationError('不能以 sb 开头')
else:
return item
# 全局钩子
# 限制出版社的名字不能等于出版社地址
def validate(self, attrs):
name = attrs.get('name')
addr = attrs.get('addr')
if name == addr:
raise ValidationError('name 和 addr 不能一样')
else:
return attrs