序列化器/反序列化器

定義Serializer

class BookInfoSerializer(serializers.Serializer):
"""圖書數(shù)據(jù)序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名稱', max_length=20)
bpub_date = serializers.DateField(label='發(fā)布日期', required=False)
bread = serializers.IntegerField(label='閱讀量', required=False)
bcomment = serializers.IntegerField(label='評論量', required=False)
image = serializers.ImageField(label='圖片', required=False)

注意:serializer不是只能為數(shù)據(jù)庫模型類定義,也可以為非數(shù)據(jù)庫模型類的數(shù)據(jù)定義。serializer是獨(dú)立于數(shù)據(jù)庫之外的存在。

創(chuàng)建Serializer對象
定義好Serializer類后,就可以創(chuàng)建Serializer對象了。
Serializer的構(gòu)造方法為:
Serializer(instance=None, data=empty, **kwarg)
說明:
1)用于序列化時,將模型類對象傳入instance參數(shù)
2)用于反序列化時,將要被反序列化的數(shù)據(jù)傳入data參數(shù)
3)除了instance和data參數(shù)外,在構(gòu)造Serializer對象時,還可通過context參數(shù)額外添加數(shù)據(jù),如
serializer = AccountSerializer(account, context={'request': request})
通過context參數(shù)附加的數(shù)據(jù),可以通過Serializer對象的context屬性獲取。

1 基本使用

1) 先查詢出一個圖書對象
from booktest.models import BookInfo
book = BookInfo.objects.get(id=2)
2) 構(gòu)造序列化器對象
from booktest.serializers import BookInfoSerializer
serializer = BookInfoSerializer(book)
3)獲取序列化數(shù)據(jù)
通過data屬性可以獲取序列化后的數(shù)據(jù)
serializer.data
{'id': 2, 'btitle': '天龍八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}
4)如果要被序列化的是包含多條數(shù)據(jù)的查詢集QuerySet,可以通過添加many=True參數(shù)補(bǔ)充說明

2 關(guān)聯(lián)對象嵌套序列化

如果需要序列化的數(shù)據(jù)中包含有其他關(guān)聯(lián)對象(即外鍵),則對關(guān)聯(lián)對象數(shù)據(jù)的序列化需要指明。

PrimaryKeyRelatedField
此字段將被序列化為關(guān)聯(lián)對象的主鍵。
hbook = serializers.PrimaryKeyRelatedField(label='圖書', read_only=True)

hbook = serializers.PrimaryKeyRelatedField(label='圖書', queryset=BookInfo.objects.all())
指明字段時需要包含read_only=True或者queryset參數(shù):
包含read_only=True參數(shù)時,該字段將不能用作反序列化使用
包含queryset參數(shù)時,將被用作反序列化時參數(shù)校驗(yàn)使用

StringRelatedField
此字段將被序列化為關(guān)聯(lián)對象的字符串表示方式(即str方法的返回值)

SlugRelatedField
此字段將被序列化為關(guān)聯(lián)對象的指定字段數(shù)據(jù)
hbook = serializers.SlugRelatedField(label='圖書', read_only=True, slug_field='bpub_date')
slug_field指明使用關(guān)聯(lián)對象的哪個字段

使用關(guān)聯(lián)對象的序列化器,會序列化該序列化對象的所有字段
hbook = BookInfoSerializer()

重寫to_representation方法
序列化器的每個字段實(shí)際都是由該字段類型的to_representation方法決定格式的,可以通過重寫該方法來決定格式。注意,to_representations方法不僅局限在控制關(guān)聯(lián)對象格式上,適用于各個序列化器字段類型。

自定義一個新的關(guān)聯(lián)字段:
class BookRelateField(serializers.RelatedField):
"""自定義用于處理圖書的字段,value表示一個字段"""
def to_representation(self, value):
return 'Book: %d %s' % (value.id, value.btitle)
指明hbook為BookRelateField類型
hbook = BookRelateField(read_only=True)

many參數(shù)
如果關(guān)聯(lián)的對象數(shù)據(jù)不是只有一個,而是包含多個數(shù)據(jù),在序列化時需要加上參數(shù)many=True

反序列化使用

使用序列化器進(jìn)行反序列化時,需要對數(shù)據(jù)進(jìn)行驗(yàn)證后,才能獲取驗(yàn)證成功的數(shù)據(jù)或保存成模型類對象。在獲取反序列化的數(shù)據(jù)前,必須調(diào)用is_valid()方法進(jìn)行驗(yàn)證,驗(yàn)證成功返回True,否則返回False。

驗(yàn)證失敗,可以通過序列化器對象的errors屬性獲取錯誤信息,返回字典,包含了字段和字段的錯誤。如果是非字段錯誤,可以通過修改REST framework配置中的NON_FIELD_ERRORS_KEY來控制錯誤字典中的鍵名。驗(yàn)證成功,可以通過序列化器對象的validated_data屬性獲取數(shù)據(jù)。

is_valid()方法還可以在驗(yàn)證失敗時拋出異常serializers.ValidationError,可以通過傳遞raise_exception=True參數(shù)開啟,REST framework接收到此異常,會向前端返回HTTP 400 Bad Request響應(yīng)。

1)validate_<field_name>
對<field_name>字段進(jìn)行驗(yàn)證

2)validate
在序列化器中需要同時對多個字段進(jìn)行比較驗(yàn)證時,可以定義validate方法來驗(yàn)證

3)validators
在字段中添加validators選項(xiàng)參數(shù),也可以補(bǔ)充驗(yàn)證行為,如
def about_django(value):
if 'django' not in value.lower():
raise serializers.ValidationError("圖書不是關(guān)于Django的")

class BookInfoSerializer(serializers.Serializer):
"""圖書數(shù)據(jù)序列化器"""
id = serializers.IntegerField(label='ID', read_only=True)
btitle = serializers.CharField(label='名稱', max_length=20, validators=[about_django])

保存

如果在驗(yàn)證成功后,想要基于validated_data完成數(shù)據(jù)對象的創(chuàng)建,可以通過實(shí)現(xiàn)create()和update()兩個方法來實(shí)現(xiàn)。
BookInfoSerializer(serializers.Serializer):
"""圖書數(shù)據(jù)序列化器"""
...
def create(self, validated_data):
"""新建"""
return BookInfo.objects.create(**validated_data)

def update(self, instance, validated_data):
    """更新,instance為要更新的對象實(shí)例"""
    instance.btitle = validated_data.get('btitle', instance.btitle)
   。。。。
    instance.save()
    return instance

實(shí)現(xiàn)了上述兩個方法后,在反序列化數(shù)據(jù)的時候,就可以通過save()方法返回一個數(shù)據(jù)對象實(shí)例了

book = serializer.save()
如果創(chuàng)建序列化器對象的時候,沒有傳遞instance實(shí)例,則調(diào)用save()方法的時候,create()被調(diào)用,相反,如果傳遞了instance實(shí)例,則調(diào)用save()方法的時候,update()被調(diào)用。

兩點(diǎn)說明:
1) 在對序列化器進(jìn)行save()保存時,可以額外傳遞數(shù)據(jù),這些數(shù)據(jù)可以在create()和update()中的validated_data參數(shù)獲取到
serializer.save(owner=request.user)

2)默認(rèn)序列化器必須傳遞所有required的字段,否則會拋出驗(yàn)證異常。但是我們可以使用partial參數(shù)來允許部分字段更新
serializer = CommentSerializer(comment, data={'content': u'foo bar'}, partial=True)

模型類序列化器

ModelSerializer與常規(guī)的Serializer相同,但提供了:
基于模型類自動生成一系列字段
基于模型類自動為Serializer生成validators,比如unique_together
包含默認(rèn)的create()和update()的實(shí)現(xiàn)

定義
比如我們創(chuàng)建一個BookInfoSerializer
class BookInfoSerializer(serializers.ModelSerializer):
"""圖書數(shù)據(jù)序列化器"""
class Meta:
model = BookInfo
fields = 'all'

model 指明參照哪個模型類
fields 指明為模型類的哪些字段生成
使用fields來明確字段:fields = ('id', 'btitle', 'bpub_date')
使用exclude可以明確排除掉哪些字段: exclude = ('image',)

默認(rèn)ModelSerializer使用主鍵作為關(guān)聯(lián)字段,但是我們可以使用depth來簡單的生成嵌套表示,depth應(yīng)該是整數(shù),表明嵌套的層級數(shù)量
可以通過read_only_fields指明只讀字段:read_only_fields = ('id', 'bread', 'bcomment')

我們可以使用extra_kwargs參數(shù)為ModelSerializer添加或修改原有的選項(xiàng)參數(shù),如:
extra_kwargs = {
'bread': {'min_value': 0, 'required': True}},
'bcomment': {'max_value': 0, 'required': True}},
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 介紹 本教程將涵蓋一個簡單的PasteBin1代碼高亮的Web API。整個過程,將逐一介紹REST framew...
    盛夏_264f閱讀 612評論 0 0
  • Serializers 序列化器允許將諸如查詢集和模型實(shí)例之類的復(fù)雜數(shù)據(jù)轉(zhuǎn)換為原生 Python 數(shù)據(jù)類型,然后可...
    lkning閱讀 1,170評論 0 1
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,711評論 19 139
  • 歡樂頌,就是歡落頌吧。 樊勝美,從小城市來打拼的姑娘,背負(fù)著家里的一切希望。被人說是“撈女”,是呀!大城市的花花世...
    joana閱讀 351評論 0 0
  • 琳是幾周前才住進(jìn)養(yǎng)老院的一位女士,87歲,肺癌晚期。她是近兩個月以來我遇到的第二個入住養(yǎng)老院的晚期癌癥患者。在這里...
    我是養(yǎng)老護(hù)理員閱讀 610評論 0 2

友情鏈接更多精彩內(nèi)容