zoukankan      html  css  js  c++  java
  • 05-序列化器ModelSerializer

    定义

    比如我们创建一个BookInfoSerializer:

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = '__all__'
    • model 指明参照哪个模型类
    • fields 指明为模型类的哪些字段生成

    我们可以在python manage.py shell中查看自动生成的BookInfoSerializer的具体实现

    >>> from booktest.serializers import BookInfoSerializer
    >>> serializer = BookInfoSerializer()
    >>> serializer
    BookInfoSerializer():
        id = IntegerField(label='ID', read_only=True)
        btitle = CharField(label='名称', max_length=20)
        bpub_date = DateField(allow_null=True, label='发布日期', required=False)
        bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
        bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
        image = ImageField(allow_null=True, label='图片', max_length=100, required=False)

     

    指定字段

    1) 使用fields来明确字段,__all__表名包含所有字段,也可以写明具体哪些字段,如

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date')

    2) 使用exclude可以明确排除掉哪些字段

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            exclude = ('image',)

    3) 显示指明字段,如:

    class HeroInfoSerializer(serializers.ModelSerializer):
        hbook = BookInfoSerializer()
    
        class Meta:
            model = HeroInfo
            fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')

    4) 指明只读字段

    可以通过read_only_fields指明只读字段,即仅用于序列化输出的字段

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date''bread', 'bcomment')
            read_only_fields = ('id', 'bread', 'bcomment')

     

    添加额外参数

    我们可以使用extra_kwargs参数为ModelSerializer添加或修改原有的选项参数

    class BookInfoSerializer(serializers.ModelSerializer):
        """图书数据序列化器"""
        class Meta:
            model = BookInfo
            fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
            extra_kwargs = {
                'bread': {'min_value': 0, 'required': True},
                'bcomment': {'min_value': 0, 'required': True},
            }
    
    # BookInfoSerializer():
    #    id = IntegerField(label='ID', read_only=True)
    #    btitle = CharField(label='名称', max_length=20)
    #    bpub_date = DateField(allow_null=True, label='发布日期', required=False)
    #    bread = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
    #    bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)

    连表查询

    1. 在models文件中定义方法, 实现外键表的查找

    class Book(BaseModel):
        name = models.CharField(max_length=64)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        img = models.ImageField(upload_to='img', default='img/default.jpg')
        publish = models.ForeignKey('Publish', on_delete=models.CASCADE)
        authors = models.ManyToManyField('Author', null=True, )
        is_delete = models.BooleanField(default=False)
    
        @property
        def publish_name(self):
            return self.publish.name
    
        @property
        def authors_name(self):
            return self.authors.values('name', 'age', 'detail__mobile').all()
    • 在多的一方定义方法, 返回查找关联表的数据, 然后使用装饰器@property将自定义的方法, 转为属性方法
    • 然后在序列化器类中将该属性方法添加到fields元组中

    2. 使用SerializerMethodField自定义序列化属性

     class BookModelSerializer(ModelSerializer):
        publish_addr = SerializerMethodField()
        
        def get_publish_addr(self, obj):
            return obj.publish.address

    注意: 使用SerializerMethodField定义的属性, 在fields字段中必须声明, 否则会报错

    自定义序列化深度连表查询

    在使用外键的情况下, 如果想要获取关联表的数据, 除了上面提到的自定义属性外, 还可以在serializers文件中定义出关联表的类, 然后使用该类来创建字段。从而达到目的, 示例代码如下:

    class PublishModelSerializer(ModelSerializer):
        class Meta:
            model = models.Publish
            fields = ('name', 'address')
    
    
    class BookModelSerializer(ModelSerializer):
    
        # 自定义连表深度 -- 子序列化方式
        publish = PublishModelSerializer()
    
        class Meta:
            model = models.Book
            fields = ('name', 'price', 'authors_name', 'publish')

    注意: 自定义的属性, 也必须在fields字段中声明, 否则会报错

    多表反序列化组件

    具体和Serializer同理, 示例代码如下:

    class BookModelDeSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 'price', 'publish', 'authors')
            extra_kwargs = {
                'img': {
                    'required': True,
                    'error_messages': {
                        'required': '图片是必填项'
                    }
                }
            }
    
        def validate_name(self, value):
            counts = models.Book.objects.filter(name=value).count()
            if counts:
                raise ValidationError({'book_name':'重复的书名'})
    
            return value
    
        def validate(self, attrs):
            publish = attrs.get('publish')
            name = attrs.get('name')
    
            count = models.Publish.objects.filter(name=publish).filter(book__name=name).count()
    
            if count:
                raise ValidationError({'msg': '该出版社存在重复的书名',
                                       'status': 2,
                                       })
    
            return attrs

    注意: ModelSerializer类已经帮我们实现了createupdate方法。所以我们只需要关注钩子的使用即可

    视图校验中的is_valid的参数raise_exception的使用

    book_serializer.is_valid(raise_exception=True)
  • 相关阅读:
    thinkphp怎么修改配置进入默认首页
    apache中怎么配置网站的默认首页
    [转]数据库更新(Update语句)查询
    ACCESS删除datagridview和数据库中的一条数据,同时更新显示的方法源码
    想ACCESS数据库插入新的用户
    C# 对象不能从 DBNull 转换为其他类型。
    windows form参数传递过程
    向ACCESS数据库中的表导入EXCEL表,在 System.Data.OleDb.OleDbException 中第一次偶然出现的“System.Data.dll”类型的异常
    C#实现Access导入导出Excel
    dataGridView1.DataSource,解决查询结果不从第一行显示,而是不断往表下面扩展问题
  • 原文地址:https://www.cnblogs.com/featherwit/p/13501158.html
Copyright © 2011-2022 走看看