DRF---Django中 模型類序列化器 ModelSerializer
關於常規的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)