drf序列化与反序列化,基表的概念

在序列化与反序列化之前,需要了解的知识点

模型表知识点

基表的概念:

  创建的基表其他表可以继承,能继承其中的字段,用于许多张表共有几个字段时,可以使用基表

基表创建方式:

class BaseModel(models.Model):
    create_time = models.DateTimeField(auto_now_add=True)
    is_delete = models.BooleanField(default=False)

    class Meta:
        # abstract默认为False
        # abstract为True不会创建此表
        abstract = True

外键字段中的断连接,反向查询与on_delete

class AuthorDetail(BaseModel):
    adders = models.CharField(max_length=255)
    mobile = models.CharField(max_length=11)
    author = models.OneToOneField(
        to='Author',
        # 反向查询都是通过related_name,默认情况都是表名小写
        # 用原生orm时,反向查询结果为多个时,需要加_set,但是一旦定义related_name,反向查询结果为多个时,也不需要加_set
        related_name='detail',
        # 断关联
        # 减缓数据库压力
        db_constraint=False,
        # on_delete 默认情况下是models.CASCADE
        # DO_NOTHING author记录删除,详情表不做任何修改
        # SET_DEFAULT 作者记录被删除时,author一对一字段会变成你设置的默认值,不过你要提前设置default
        # SET_NULL 作者记录被删除时,author一对一字段会变成空(null) 也要提前设置null=True
        on_delete=models.DO_NOTHING
    )

    class Meta:
        db_table = 'day71_author_detail'
        verbose_name = '作者详情'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '%s的详情' % self.author.name

注:

  断连情况下,两张表已经没有数据库关系了,再去操作数据库不会级联更新级联删除

  我们加的on_delete=models.CASCADE是让orm通过逻辑进行级联删除

序列化与反序列化(ModelSerializer)

序列化

class Publishserializers(serializers.ModelSerializer):
    class Meta:
        model = models.Publish
        fields = ('name', 'adders')


class Bookserializers(serializers.ModelSerializer):
    # 自定义字段必须写在fields中
    # 了解: 该方式设置的序列化字段,必须在fields中声明
    # 自定义连表深度 - 子序列化方式
    # 如果自定义字段与model类中的字段重名时,会走自定义字段
    publish = Publishserializers()
    class Meta:
        model = models.Book
        fields = ('name', 'price', 'publish', 'get_author', 'gender')

        # 所有字段
        # fields = '__all__'
        # 与fields不共存,exclude排除哪些字段
        # exclude = ('id', 'is_delete', 'create_time')
        # 自动连表深度
        # depth = 1

序列化fields中可以添加模型类中序列化插拔属性,

说的简单点就是,在模型类中定义方法,最好是用property装饰器装饰

# 序列化插拔式属性 - 完成自定义字段名完成连表查询
    @property
    def get_author(self):
        # print(self.authors, type(self.authors))
        return self.authors.values('name', 'age')

模型类中的插拔式属性,在序列化中的fields可写可不写

注:

  自定义字段最好不要与模型表中的字段重名

反序列化

class BookDeserializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = ('name', 'price', 'publish', 'authors')
        # extra_kwargs为了反序列化时添加系统校验
        extra_kwargs = {
            'name': {
                'max_length': 10,
                'min_length': 3,
                # required默认为True,所以默认为必填字段
                'required': True,
                'error_messages': {
                    'max_length': '姓名最长10位',
                    'min_length': '姓名最短3位',
                    'required': '姓名必填'
                }
            },
        }
    
    # 局部钩子
    def validate_name(self, value):
        if 'g' in value:
            raise exceptions.ValidationError('你这个鸡贼')
        return value

    # 全局钩子
    def validate(self, attrs):
        # 外键字段前端传过来的都是id值,但是后端会将其转成对象,
        # 如果传过来的id值,并不在数据库中,会直接报错,如果我们写了raise_exception=True会直接将错返回给前端
        book_obj = models.Book.objects.filter(publish=attrs.get('publish'), name=attrs.get('name'))
        # print(book_obj)
        if book_obj:
            raise exceptions.ValidationError({"name": '书名重复'})
        return attrs

序列化与反序列化可以合并,上面只是方便演示

"""
1) fields中设置所有序列化与反序列化字段
2) extra_kwargs划分只序列化或只反序列化字段
    write_only:只反序列化
    read_only:只序列化
    自定义字段默认只序列化(read_only)
3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则
"""


class V2Bookserializers(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        fields = ('name', 'img', 'price', 'authors', 'publish', 'publish_name', 'get_author')
        extra_kwargs = {
            'img': {
                'read_only': True
            },
            'publish_name': {
                'read_only': True
            },
            'get_author': {
                'read_only': True
            },
            'name': {
                'max_length': 10,
                'min_length': 3,
                'error_messages': {
                    'max_length': '姓名最长10位',
                    'min_length': '姓名最短3位',
                    'required': '姓名必填'
                }
            }
        }

    def validate_name(self, value):
        if 'g' in value:
            raise exceptions.ValidationError('你这个鸡贼')
        return value

    def validate(self, attrs):
        book_obj = models.Book.objects.filter(name=attrs.get('name'), publish=attrs.get('publish'))
        if book_obj:
            raise exceptions.ValidationError({'name': '同一出版社书名不能重复'})
        return attrs

再次提醒:

  自定义连表深度(自定义属性)默认为read_only只参加序列化

当我仰望星空, 看见了涛涛江水, 看见了妻妾成群

猜你喜欢

转载自www.cnblogs.com/asdaa/p/11689849.html
今日推荐