drf序列化类:
- Serializer: 没有关联模型类,需要重写update和create方法
- ModelSerializer:关联模型类,内部已经写好update和create方法,可以不用重写
Serializer序列化器的书写
class AuthorSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=10)
phone = serializers.CharField(max_length=11,min_length=11)
address = serializers.CharField(max_length=200)
def validate_字段名(self,value):
#对该字段进行进一步的校验
#对于钩子函数,勾出什么,就需要return什么
return value
def validate(self,attrs):
#拿到多个字段数据,进行校验
#校验的逻辑
return attrs
def update(self,instance,validated_data):
#更新的逻辑
return instance
#返回值自己决定,当view调用了ser.save()方法后,会调用该update方法,之后的ser.data()拿到的就是update的返回值
def create(self,validated_data):
#创建的逻辑
return 自己定义的返回值
#返回值自己决定,当view调用了ser.save()方法后,会调用该create方法,之后的ser.data()拿到的就是create的返回值
ModelSerializer序列化器书写
class AuthorModelSerializer(serializers.ModelSerializer):
class Meta:
model = models.Author
fields = ['id','name','phone','address']
extra_kwargs={
'id':{'read_only':True},
'name':{
'max_length':10,
'min_length':3,
'error_messages':{
'max_length':"名字长度不能大于10",
'min_length':"名字长度不能小于3"
}
},
'phone':{
'max_length':11,
'min_length':11
}
}
def validate_字段名(self,value):
pass
def validate(self,attrs):
pass
#对于create和update方法,在ModelSerializer中已经实现了,可以不重写
1、字段
#常用
max_length 字符串最大长度
min_length 字符串最小长度
max_value 数值最大值
min_value 数值最小值
default 字段反序列化时,如果没有传入数据,就使用默认值
error_messages 指定字段中,某个校验字段不通过时,输入的错误提示信息
read_only 该字段仅用于序列化输出,默认False
write_only 该字段仅用于反序列化输入,默认False
required 字段反序列化时必须输入数据,默认是True
#不常用
all_blank 是否允许为空,默认False
allow_null 是否传入None,默认False
label 用于html展示API页面时,显示的字段名称
help_text 用于html展示API页面时,展示的字段帮助提示信息
validators 指明该字段使用的验证器
#source字段的功能
1、重命名:user_name = serialziers.CharField(source='name')
2、跨表查询:teacher_name = serializers.CharField(source='teacher.name')
3、choice拿值:sex = serializers.Charfield(source='get_sex_display')
模型类中书写:sex = models.IntegerField(choice=((1,'男'),(0,'女')),default=0)
通过source='get_字段_display',拿到choice中对应的数据
2、钩子函数
钩子函数作用:字段校验,只能做一些最基本的校验。要进一步的校验,需要通过在钩子函数写校验流程。
有局部钩子和全局钩子:
- 局部钩子:校验的是某个字段,如:手机号码校验 (def validate_字段名(self,value))
- 全局钩子:需同时校验多个字段,如:设置密码,需要校验两次密码是否一致 (def validate(self,attrs) )
局部钩子例子:
def validate_phone(self,value):
print(value)
if re.findall('^1[3456789]\d{9}$', value):
return value
raise ValidationError('手机格式有问题,请检查!!')
全局钩子例子:
def validate(self,attrs):
new_pwd = attrs.get('password')
resure_pwd = attrs.get("resure_password")
if new_pwd == resure_pwd:
return attrs
raise ValidationError("两次输入的密码不一致!!")
3、create和update方法
def create(self,validated_data):
try:
author = models.Auhtor.objects.create(**validated_data)
return author
except Exception as e:
raise ValidationError(str(e))
def update(self,instance,validated_data):
try:
for key,value in validated_data.items():
instance.key=value
instance.save()
return Validated_data
except Exception as e:
raise ValidationError(str(e))
4、序列化器嵌套
4.1、通过字段 :PrimaryKeyRelatedField :获取到关联字段的主键值
class StudentModelSerializer(serializers.ModelSerialzier):
classmate_id = serializers.PrimaryKeyRelatedField(label='班级id',read_only=True)
#拿到的是学生所在班级的id
class Meta:
model = models.Student
fields = ['id','name','number','classmate_id']
4.2、通过字段:StringRelatedField,拿到模型类的__str方法的返回值
StringRelatedField拿到的就是模型类的__str__方法
#在模型类中,设置__str__方法
def __str__(self):
//返回值是由自己决定的,只能返回字符串,不然会报错
reutrn self.name
class StudentModelSerializer(serializers.ModelSerializer):
classmate_dic = serializers.StringRelatedField(label='班级信息')
class Meta:
model = models.Student
fields = ['id','name','number','classmate_dic']
4.3、通过字段接收关联的序列化对象
class ClassMate(serializers.ModelSerializer):
class Meta:
model = models.ClassMate
fields = ['id','number']
class Student(serializers.ModelSerializer):
classmate = ClassMate()
class Meta:
model = models.Student
fields = ['id','name','number','classmate']
上面的当前模型类是属于多的一方,外键存在的一方。拿到的关联对象只有一个数据。
4.4、如果当前模型类是属于一的一份,拿到的关联对象是有多个数据。
-
此时,只需要加参数 many=True
classmate_id = serializers.PrimaryKeyRelatedField(label='班级id',read_only=True,many=True) classmate_dic = serializers.StringRelatedField(label='班级信息',many=True) classmate = ClassMate(many=True)
5、视图使用时,序列化器的流程
1、处理get请求时,是进行序列化操作,不会走字段校验和钩子函数。
2、post请求时,新建数据,先走字段校验、再走钩子函数、最后执行create方法
ser.is_valid() 这个是在进行字段校验、钩子校验
ser.save() 这是在走create方法(如果实例化对象传递进来的参数只有data时)
此时的ser.data 拿到的是create方法的返回值
3、put/patch请求时,更新数据,先走字段校验、再走钩子函数,最后执行update方法
ser.is_valid() 这个是在进行字段校验和钩子校验
ser.save()这个是在走update方法,(实例化对象传递进来的参数有instance和data时)
此时的ser.data拿到的是update方法的返回值