一:标准校验流程:
1:小测试:
>>> from books.models import *
>>> from books.serializers import *
# 1:获取前端传值
>>> book_info = {"btitle": "围城","bpub_date": "1999-9-9"}
# 2:实例化序列器对象
>>> bs = BookInfoSerializers(data = book_info)
# 3: 启动校验流程
>>> bs.is_valid()
False
# 4:查看启动失败原因
>>> bs.errors
{'id': [ErrorDetail(string='This field is required.', code='required')], 'is_delete': [ErrorDetail(string='This field is required.', code='required')], 'bread': [ErrorDetail(string='This field is required.', code='required')], 'image': [ErrorDetail(string='No file was submitted.', code='required')], 'bcomment': [ErrorDetail(string='This field is required.', code='required')]}
错误原因?
答:我们在定义序列化器对象的时候,没有加约束条件,导致序列器默认所有字段都必须传。
序列器对象约束规定:
参照模型类定义,但是必须比模型类定义的更加严格。
2:校验流程:


3:校验的约束条件:
3.1:根据模型类定义序列化约束条件。


3.2:约束条件校验:

# allow_blank指的是允许是‘空字符。
# trim_whitespace 指的是如果传入 “ 围城 ” --->序列化后变成 ---> "围城"
btitle = serializers.CharField(max_length=20, min_length=5, allow_blank=True, trim_whitespace=True)
bread = serializers.IntegerField(required=False, max_value=99999999, min_value=0)
4:三种自定义校验方式:
4.1:自定义校验—validators:
def check_btitle(value):
if "django" not in value:
raise serializers.ValidationError("这不是一个关于django的书")
class BookInfoSerializers(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
# allow_blank指的是允许是‘空字符。
# trim_whitespace 指的是如果传入 “ 围城 ” --->序列化后变成 ---> "围城"
btitle = serializers.CharField(max_length=20,
validators= [check_btitle]
)
>>> from books.serializers import *
>>> book_info = {"btitle": "django妹妹", "bpub_date": "1998-10-9"}
>>> bs = BookInfoSerializers(data = book_info)
>>> bs.is_valid()
True
>>> bs.validated_data
OrderedDict([('btitle', 'django妹妹'), ('bpub_date', datetime.date(1998, 10, 9))])
4.2:自定义校验之validate_<字段名>:
class BookInfoSerializers(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
# btitle = serializers.CharField(max_length=20,
# validators= [check_btitle]
# )
bpub_date = serializers.DateField()
bread = serializers.IntegerField(required=False, max_value=99999999, min_value=0)
bcomment = serializers.IntegerField(required=False)
is_delete = serializers.BooleanField(required=False)
image = serializers.ImageField(required=False)
btitle = serializers.CharField(max_length=20)
def validate_btitle(self, value):
if "django" not in value:
raise serializers.ValidationError("这不是一本关于django的书")
# 切记,一定要返回字段的有效值,如果不返回会造成当前字段数据丢失
return value
>>> from books.serializers import *
>>> book_info = {"btitle": "django妹妹", "bpub_date": "1998-10-9"}
>>> bs = BookInfoSerializers(data = book_info)
>>> bs.is_valid()
True
>>> bs.validated_data
OrderedDict([('bpub_date', datetime.date(1998, 10, 9)), ('btitle', 'django妹妹')])
4.3:自定义校验之validate
def validate(self,attrs):
btitle = attrs.get('btitle')
if 'django' not in btitle:
raise serializers.ValidationError('这不是一本关于django的书')
# 相同方式对别的字段校验...略
# 返回最终的有效数据,如果不返回,后果就是丢失最终的有效数据
return attrs
>>> from books.serializers import *
>>> book_info = {"btitle": "django妹妹", "bpub_date": "1998-10-9"}
>>> bs = BookInfoSerializers(data = book_info)
>>> bs.is_valid()
True
>>> bs.validated_data
OrderedDict([('bpub_date', datetime.date(1998, 10, 9)), ('btitle', 'django妹妹')])
5:校验流程:

二:新建/更新流程:
序列化器中的create方法和update方法:
为什么要重写序列化器中的create(update)方法??
答:因为我的序列化器继承于serializers.Serializer,而Serializer继承于BaseSerializers,BaseSerializers并没有实现只是定义了这个两个方法,所以需要子类继承重写。

1:新建模型类对象保存到数据库:
def create(self, validated_data):
instance = BookInfo.objects.create(**validated_data)
return instance
>>> from books.serializers import *
>>> book_info = {"btitle": "django妹妹", "bpub_date": "1998-10-9"}
>>> bs = BookInfoSerializers(data = book_info)
>>> bs.is_valid()
True
>>> bs.save()
<BookInfo: django妹妹>
2:更新模型类对象保存到数据库:
为什么要使用setattr进行更新??
答: 由于我们不知道传入的校验字段有哪些,所以不能根据字段进行一一修改,所以才采用setattr进行更新。
# setattr(对象,key,value)函数的作用: 给一个对象的某个属性设置值
# 例如:
setattr(hero, 'hname', '任善文')
def update(self, instance, validated_data):
for field, value in validated_data.items():
setattr(instance,field,value)
instance.save()
return instance
>>> from books.serializers import *
>>> book_info = {"btitle": "django坏坏", "bpub_date": "1998-10-9"}
>>> book = BookInfo.objects.get(pk = 5)
>>> bs = BookInfoSerializers(instance= book , data= book_info)
>>> bs.is_valid()
True
>>> bs.save()
<BookInfo: django坏坏>
3:反序列化流程:

三:反序列化的补充说明:
1:PrimaryKeyRelatedField作用于反序列化:
把主键反序列化成关联的对象:
class HeroInfoSerialiser(serializers.Serializer):
GENDER_CHOICES = (
(0, 'female'),
(1, 'male')
)
hname = serializers.CharField(max_length=20)
hgender = serializers.ChoiceField(choices=GENDER_CHOICES, default=0,required=False)
hcomment = serializers.CharField(max_length=200,required=False)
is_delete = serializers.BooleanField(default=False)
hbook = serializers.PrimaryKeyRelatedField(
queryset=BookInfo.objects.all()
)
注意: hgender = serializers.ChoiceField(choices=GENDER_CHOICES, default=0,required=False),这里必须用ChoiceField类型。
>>> from books.serializers import *
>>> from books.models import *
>>> hero_info = {"hname": "renshanwen", "hgender": 1, "hbook": 5}
>>> hs = HeroInfoSerialiser(data = hero_info)
>>> hs.is_valid()
True
>>> hs.validated_data
OrderedDict([('hname', 'renshanwen'), ('hgender', 1), ('is_delete', False), ('hbook', <BookInfo: django坏坏>)])
2:全更新(全校验),部分更新(部分校验)
-
全更新其本质是 —— 全校验,必要字段必传必校验;
Serializer(instance=模型类对象,data=参数):默认情况下是全校验 -
部分更新其本质是 —— 部分校验,必要字段可传可不传,传什么就校验什么;
Serializer(instance=模型类对象,data=参数,partial=True):partial=True表明序列化器后续的校验逻辑为部分校验;
解决的问题就是更新的时候,我想要更改一个字段,但是还要传那些必要字段,加上这个参数partial = True 必需要传的字段就可以不传了。
案例: 修改郭靖hcomment 降龙十八掌 修改成 降龙十九掌
核心代码:
hs = HeroInfoSerialiser(instance= hero, data= hero_info, partial = True)
class HeroInfoSerialiser(serializers.Serializer):
GENDER_CHOICES = (
(0, 'female'),
(1, 'male')
)
hname = serializers.CharField(max_length=20)
hgender = serializers.ChoiceField(choices=GENDER_CHOICES, default=0,required=False)
hcomment = serializers.CharField(max_length=200,required=False)
is_delete = serializers.BooleanField(default=False)
hbook = serializers.PrimaryKeyRelatedField(
queryset=BookInfo.objects.all()
)
def update(self, instance, validated_data):
for field, value in validated_data.items():
setattr(instance, field, value)
instance.save()
return instance
运行情况:
>>> from books.serializers import *
>>> from books.models import *
>>> hero_info = {"hcomment": "降龙十九掌"}
>>> hero = HeroInfo.objects.get(pk=1)
>>> hs = HeroInfoSerialiser(instance= hero, data= hero_info, partial = True)
>>> hs.is_valid()
True
3:save方法传递关键字参数:
作用:传递的关键字参数,会被合并到validated_data有效数据中,作用于create和update方法!
运用:如果前端没有传递给我们的字段,我们向新建或者更新的时候手动设置默认值,这个时候就需要save方法了。
案例:在新建善文正传这本书的时候,默认阅读量和评论量分别是100,200。
>>> book = {"btitle": "善文正传", "bpub_date": "1998-10-9"}
>>> bs = BookInfoSerializers(data = book)
>>> bs.is_valid()
True
>>> bs.save(bread= 100, bcomment= 200)
<BookInfo: 善文正传>

浙公网安备 33010602011771号