飞行的猪哼哼

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一:标准校验流程:

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有效数据中,作用于createupdate方法!

运用:如果前端没有传递给我们的字段,我们向新建或者更新的时候手动设置默认值,这个时候就需要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: 善文正传>

在这里插入图片描述

posted on 2020-09-20 14:35  飞行的猪哼哼  阅读(53)  评论(0)    收藏  举报