序列化器做用:
1.進行數據的校驗
2.對數據對象進行轉換
序列化: 模型類對象 -----> python字典 用於輸出, 返回給前端使用
反序列化: 前端傳送的數據 -------> 通過驗證 -----> python的字典 用於輸入 接受前端數據時使用
序列化器做用: 幫助咱們進行序列化, 反序列化
總結 :
在開發REST API接口時,咱們在視圖中須要作的最核心的事是:
將數據庫數據序列化爲前端所須要的格式,並返回;
將前端發送的數據反序列化爲模型類對象,並保存到數據庫中。
在開發REST API的視圖中,雖然每一個視圖具體操做的數據不一樣,但增、刪、改、查的實現流程基本套路化,因此這部分代碼也是能夠複用簡化編寫的:
增:校驗請求數據 -> 執行反序列化過程 -> 保存數據庫 -> 將保存的對象序列化並返回
刪:判斷要刪除的數據是否存在 -> 執行數據庫刪除
改:判斷要修改的數據是否存在 -> 校驗請求的數據 -> 執行反序列化過程 -> 保存數據庫 -> 將保存的對象序列化並返回
查:查詢數據庫 -> 將數據序列化並返回
1.序列化的定義
根據模型類定義序列化器
示例:
序列化: 模型類對象 -----> python字典 用於輸出, 返回給前端使用
反序列化: 前端傳送的數據 -------> 通過驗證 ----->save python的字典 用於輸入 接受前端數據時使用
序列化器做用: 幫助咱們進行序列化, 反序列化
注意: serializer不是隻能爲數據庫模型類定義,也能夠爲非數據庫模型類的數據定義
2. 建立serializer對象
定義好Serializer類後,就能夠建立Serializer對象了。
Serializer的構造方法爲:
說明:
1)用於序列化時,將模型類對象傳入instance參數
2)用於反序列化時,獲取數據前進行驗證 ( is_valid() ), 將要被反序列化的數據傳入data參數
3)除了instance和data參數外,在構造Serializer對象時,還可經過context參數額外添加數據,如
serializer = AccountSerializer(account, context={'request': request})
經過context參數附加的數據,能夠經過Serializer對象的context屬性獲取。
3. 序列化的使用
1. 基本使用
1) 先查詢出一個圖書對象
2) 構造序列化器對象
3)獲取序列化數據
經過data屬性能夠獲取序列化後的數據
4)若是要被序列化的是包含多條數據的查詢集QuerySet,能夠經過添加many=True參數補充說明
book_qs = BookInfo.objects.all()
serializer = BookInfoSerializer(book_qs, many=True)
serializer.data
# [OrderedDict([('id', 2), ('btitle', '天龍八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]),
# OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]),
# OrderedDict([('id', 4), ('btitle', '雪山飛狐'), ('bpub_date', '1987-11-11'), ('bread', 58), ('bcomment', 24), ('ima None)]),
# OrderedDict([('id', 5), ('btitle', '西遊記'), ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im', 'booktest/xiyouji.png')])]
2. 關聯對象
1) PrimaryKeyRelatedField
此字段將被序列化爲關聯對象的主鍵。
指明字段時須要包含read_only=True或者queryset參數:
包含read_only=True參數時,該字段將不能用做反序列化使用
包含queryset參數時,將被用做反序列化時參數校驗使用查詢
4. 反序列化的使用
1. 驗證
在獲取反序列化的數據前,必須調用
is_valid()方法進行驗證,驗證成功返回True,不然返回False。
驗證失敗,能夠經過序列化器對象的errors屬性獲取錯誤信息,返回字典,包含了字段和字段的錯誤。若是是非字段錯誤,能夠經過修改REST framework配置中的
NON_FIELD_ERRORS_KEY來控制錯誤字典中的鍵名。
驗證成功,能夠經過序列化器對象的
validated_data屬性獲取數據。
如咱們前面定義過的BookInfoSerializer
經過構造序列化器對象,並將要反序列化的數據傳遞給data構造參數,進而進行驗證
is_valid()方法還能夠在驗證失敗時拋出異常serializers.ValidationError,能夠經過傳遞raise_exception=True參數開啓,REST framework接收到此異常,會向前端返回HTTP 400 Bad Request響應。
# Return a 400 response if the data was invalid.
serializer.is_valid(raise_exception=True)
2.保存
若是在驗證成功後,想要基於validated_data完成數據對象的建立,能夠經過實現create()和update()兩個方法來實現。
class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
def create(self, validated_data):
"""新建"""
return BookInfo(**validated_data)
def update(self, instance, validated_data):
"""更新,instance爲要更新的對象實例"""
instance.btitle = validated_data.get('btitle', instance.btitle)
instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
instance.bread = validated_data.get('bread', instance.bread)
instance.bcomment = validated_data.get('bcomment', instance.bcomment)
return instance
若是須要在返回數據對象的時候,也將數據保存到數據庫中,則能夠進行以下修改
class BookInfoSerializer(serializers.Serializer):
"""圖書數據序列化器"""
...
def create(self, validated_data):
"""新建"""
return BookInfo.objects.create(**validated_data)
def update(self, instance, validated_data):
"""更新,instance爲要更新的對象實例"""
instance.btitle = validated_data.get('btitle', instance.btitle)
instance.bpub_date = validated_data.get('bpub_date', instance.bpub_date)
instance.bread = validated_data.get('bread', instance.bread)
instance.bcomment = validated_data.get('bcomment', instance.bcomment)
instance.save()
return instance
實現了上述兩個方法後,在反序列化數據的時候,就能夠經過save()方法返回一個數據對象實例了
若是建立序列化器對象的時候,沒有傳遞instance實例,則調用save()方法的時候,create()被調用,相反,若是傳遞了instance實例,則調用save()方法的時候,update()被調用。
from db.serializers import BookInfoSerializer
data = {'btitle': '封神演義'}
serializer = BookInfoSerializer(data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 封神演義>
from db.models import BookInfo
book = BookInfo.objects.get(id=2)
data = {'btitle': '倚天劍'}
serializer = BookInfoSerializer(book, data=data)
serializer.is_valid() # True
serializer.save() # <BookInfo: 倚天劍>
book.btitle # '倚天劍'
兩點說明:
1) 在對序列化器進行save()保存時,能夠額外傳遞數據,這些數據能夠在create()和update()中的validated_data參數獲取到
2)默認序列化器必須傳遞全部required的字段,不然會拋出驗證異常。可是咱們能夠使用partial參數來容許部分字段更新
5. 模型類serializers
ModelSerializer與常規的Serializer相同,但提供了:
基於模型類自動生成一系列字段 # 自動生成字段
基於模型類自動爲Serializer生成validators,好比unique_together # 惟一約束
包含默認的create()和update()的實現 # 默認的兩種方法
1. 定義
demo
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta: # Meta是一個內部類,它用於定義一些Django模型類的行爲特性
model = BookInfo
fields = '__all__'
model 指明參照哪一個模型類
fields 指明爲模型類的哪些字段生成
2. 指定字段
1) 使用fields來明確字段,__all__表名包含全部字段,也能夠寫明具體哪些字段,如
2) 使用
exclude能夠明確排除掉哪些字段
3) 默認ModelSerializer使用主鍵做爲關聯字段,可是咱們能夠使用depth來簡單的生成嵌套表示,depth應該是整數,代表嵌套的層級數量。如:
class HeroInfoSerializer2(serializers.ModelSerializer):
class Meta:
model = HeroInfo
fields = '__all__'
depth = 1
造成的序列化器以下:
4) 顯示指明字段,如:
class HeroInfoSerializer(serializers.ModelSerializer):
hbook = BookInfoSerializer()
class Meta:
model = HeroInfo
fields = ('id', 'hname', 'hgender', 'hcomment', 'hbook')
5) 指明只讀字段
能夠經過
read_only_fields指明只讀字段,即僅用於序列化輸出的字段
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數據序列化器"""
class Meta:
model = BookInfo
fields = ('id', 'btitle', 'bpub_date', 'bread', 'bcomment')
read_only_fields = ('id', 'bread', 'bcomment')
3. 添加額外參數
咱們能夠使用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='閱讀量', min_value=2147483647, min_value=0, required=True)
# bcomment = IntegerField(label='評論量', min_value=2147483647, min_value=0, required=True)