DRF---Django中 模型类序列化器 ModelSerializer

版权声明:转载请标明出处 https://blog.csdn.net/gymaisyl/article/details/84073303

关于常规的Serializer使用方法,可以参考 常规的Serializer讲解


如果我们需要使用的序列化器,是对应Django的模型类,那么,DRF已经为我们提供了ModelSerializer模型类序列化器,可以满足我们的需求,快速创建一个Serializer类。

ModelSerializer和普通Serializer的区别

①:基于模型类自动生成一系列字段;
②:基于模型类自动为Serializer生成validators,比如unique_together;
③:包含默认的create()和update()的实现。

现在,我们就从实际的操作中来看一下ModelSerializer,应该如何使用。

本文代码实现前提:我已经在子应用的models.py文件中定义了几个模型类

# 定义图书模型类BookInfo
class BookInfo(models.Model):
    btitle = models.CharField(max_length=20, verbose_name='名称')
    bpub_date = models.DateField(verbose_name='发布日期')
    bread = models.IntegerField(default=0, verbose_name='阅读量')
    bcomment = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')
    image = models.ImageField(upload_to='booktest', verbose_name='图片', null=True)
    
    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.btitle
#定义英雄模型类HeroInfo
class HeroInfo(models.Model):
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    hname = models.CharField(max_length=20, verbose_name='名称')
    hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
    hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息')
    hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    def __str__(self):
        return self.hname

一·定义

我们现在对于BookInfo,创建一个序列化器

class BookInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        # 指明关联的模型类
        model = BookInfo
        # 指明返回的字段
        fields = "__all__"

我们现在对于HeroInfo,创建一个序列化器

class HeroInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = HeroInfo
        fields = '__all__'

申明:

  • model 指明参照哪个模型类
  • fields 指明为模型类的哪些字段生成

前面我们介绍了ModelSerializer的一个特性就是,可以根据模型类来决定创建的序列化器会有哪些字段,为了验证,我们可以看一下序列化器在不传参的情况下,是什么样的:

In [3]: s = BookInfoModelSerializer()                                                                                               

In [4]: s                                                                                                                           
Out[4]: 
BookInfoModelSerializer():
    id = IntegerField(label='ID', read_only=True)
    btitle = CharField(label='名称', max_length=20)
    bpub_date = DateField(label='发布日期')
    bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
    bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
    is_delete = BooleanField(label='逻辑删除', required=False)
    image = ImageField(allow_null=True, label='图片', max_length=100, required=False)

由此可见,ModelSerializer确实可以满足我们的需求,而不需要我们把字段一个一个进行手敲了。

字段的指定

(1)fields
上面我在代码中也标注了,fields可以指定我们定义的序列化器拥有的字段;__all__ 是默认包含原模型类的所有字段;当然了,我们也是可以写明我们具体需要哪些字段:

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

(2)exclude
exclude的作用是可以排除哪些字段不可以用

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

注意:exclude和fields在一个序列化器中,只能存在一个,不然会报错的。

(3)关联字段处理

ModelSerializer会默认使用主键作为关联字段,如下:

hbook = PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())

我们可以通过 depth 来简单的设置嵌套模式:
现在将HeroInfo序列化器改成这样:

class HeroInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = HeroInfo
        fields = '__all__'
        depth = 1

然后我们的外键hbook就变成这样了:

    hbook = NestedSerializer(read_only=True):
        id = IntegerField(label='ID', read_only=True)
        btitle = CharField(label='名称', max_length=20)
        bpub_date = DateField(label='发布日期')
        bread = IntegerField(label='阅读量', max_value=2147483647, min_value=-2147483648, required=False)
        bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=-2147483648, required=False)
        is_delete = BooleanField(label='逻辑删除', required=False)
        image = ImageField(allow_null=True, label='图片', max_length=100, required=False)

注意:depth应该是整数,表明嵌套的层级数量。

(4)显示指名字段–包括关联字段的设置

参考代码:

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

注意,如果想设置指名的字段,并且指名的字段包括关联字段,而且关联字段想通过自己设置,比如这里的hbook = BookInfoModelSerializer() , 那么,我们必须要在fields中写上这个关联字段,不能以为外面写了关联字段,里面可以不写,那是不行的。

(5)read_only_fields
指名只读字段,用于序列化的输出

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

序列化器的额外参数的传递

extra_kwargs参数可以添加或修改ModelSerializer原有的选项参数;

比如在上面的代码中,我们有一个阅读量和评论的数据的最小值,默认是负数min_value=-2147483648,,这肯定是不合理的,所以就需要修改。

在BookInfoModelSerializer 中添加 extra_kwargs这个参数,并把想要修改的选项参数进行修改或者增加就可以了。

 extra_kwargs = {
                           'bread': {'min_value': 0, 'required': True},
                           'bcomment': {'min_value': 0, 'required': True},
        }  

修改后的数据如下:

In [3]: s = BookInfoModelSerializer()                                                                                               

In [4]: s                                                                                                                           
Out[4]: 
BookInfoModelSerializer():
    id = IntegerField(label='ID', read_only=True)
    btitle = CharField(label='名称', max_length=20)
    bpub_date = DateField(label='发布日期')
    bread = IntegerField(label='阅读量', max_value=2147483647, min_value=0, required=True)
    bcomment = IntegerField(label='评论量', max_value=2147483647, min_value=0, required=True)
    is_delete = BooleanField(label='逻辑删除', required=False)
    image = ImageField(allow_null=True, label='图片', max_length=100, required=False)

猜你喜欢

转载自blog.csdn.net/gymaisyl/article/details/84073303