DRF框架之Serializer序列化器的反序列化操作
昨天,我們完成了Serializer序列化器的反序列化操作,那麼今天我們就來學習Serializer序列化器的最後一點知識,反序列化操作。
首先,我們定要明確什麼是反序列化操作?
反序列化操作:JOSN資料 --> 字典資料 -->驗證通過的字典資料 --> 模型資料
我們在進行反序列化操作時,首先要保證就是拿到的字典資料一定要通過認證。
反序列化操作的步驟:
1. 定義一個序列化器(這裡我們採用昨天定義好的序列化器即可)。
class BookInfoSerializer(serializers.Serializer): '''定義圖書序Serializer序列化器''' # 這裡的欄位需要和模型類中的欄位名、欄位型別、約束一致 id = serializers.IntegerField(label='ID', read_only=True) btitle = serializers.CharField(label='名稱', max_length=20) bpub_date = serializers.DateField(label='釋出日期', required=False) bread = serializers.IntegerField(label='閱讀量', required=False) bcomment = serializers.IntegerField(label='評論量', required=False)
2. 準備JSON資料或字典資料
data = {'btitle':'大話西遊','bpub_date':'2020-02-06'}
3. 驗證字典資料
我們使用序列化器物件點出is_valid()方法進行驗證,驗證成功返回True,否則返回False。
3.1 驗證通過
當字典資料通過校驗時,我們可以通過序列化器物件點出validated_data屬性獲取到校驗成功後的字典資料。
>>> data = {'btitle':'大話西遊','bpub_date':'2020-02-06'} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() True >>> s.validated_data OrderedDict([('btitle', '大話西遊'), ('bpub_date', datetime.date(2020, 2, 6))])
3.2 驗證未通過
當字典資料未通過校驗時,我們可以通過序列化器物件點出errors屬性獲取到錯誤資訊。
>>> data = {'bpub_date': 123} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() False >>> s.validated_data {} >>> s.errors {'btitle': [ErrorDetail(string='This field is required.', code='required')], 'bpub_date': [ErrorDetail(string='Date has wrong format. Use one of these formats instead: YYYY-MM-DD.', code='invalid')]}
3.3 對單一欄位進行驗證
我們需要在序列化器類中定義一個名字為(validate_欄位名)的方法,來補充驗證邏輯。
def validate_btitle(self, value): ''' 對btitle欄位進行驗補充 :param value: 前段傳遞的btitle資料 :return: 驗證成功:返回value;驗證失敗:返回錯誤資訊 '''
當驗證失敗時,我們使用raise丟擲異常的方式來返回錯誤資訊。
例如:
# 補充單一欄位的驗證邏輯 def validate_btitle(self, value): ''' 對btitle欄位進行驗補充 :param value: 前段傳遞的btitle資料 :return: 驗證成功:返回value;驗證失敗:返回錯誤資訊 ''' # 驗證邏輯 if 'django' not in value: # 失敗 raise serializers.ValidationError('btitle資料錯誤資訊') # 成功 return value
Shell測試程式碼:
>>> from booktest.serializers import BookInfoSerializer >>> data = {'btitle': 'python'} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() False >>> s.errors {'btitle': [ErrorDetail(string='btitle資料錯誤資訊', code='invalid')]} >>> data = {'btitle': 'python_django'} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() True >>> s.validated_data OrderedDict([('btitle', 'python_django')])
3.4 對所有欄位進行擴充套件驗證
我們需要在序列化器中定義一個名字為(validate())的方法,來補充對所有欄位進行擴充套件驗證的邏輯。
def validate(self, attrs): ''' 對多個欄位進行驗證 :param attrs: 前段傳遞的字典資料 :return: 驗證成功:返回attrs;驗證失敗:返回錯誤資訊 '''
同樣,我們也需要使用raise丟擲異常資訊。
例如:
def validate(self, attrs): ''' 對多個欄位進行驗證 :param attrs: 前段傳遞的字典資料 :return: 驗證成功:返回attrs;驗證失敗:返回錯誤資訊 ''' # 驗證邏輯:這裡需要驗證的是bread大於bcomment bread = attrs.get('bread') bcomment = attrs.get('bcomment') if bread < bcomment: # 失敗 raise serializers.ValidationError('bread需要大於bcomment') # 成功 return attrs
Shell測試程式碼:
>>> from booktest.serializers import BookInfoSerializer >>> data = {'btitle': 'about django', 'bread': 10, 'bcomment': 20} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() False >>> s.errors {'non_field_errors': [ErrorDetail(string='bread需要大於bcomment', code='invalid')]} >>> data = {'btitle': 'about django', 'bread': 50, 'bcomment': 20} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() True >>> s.validated_data OrderedDict([('btitle', 'about django'), ('bread', 50), ('bcomment', 20)])
4. 驗證後的字典資料 ---> 模型資料
這裡,我們已將到了資料反序列化的最後一步操作了。
同樣,我們也應該知道,將驗證後的字典資料轉模型資料的實質,其實就是將驗證過的字典資料新增到資料庫中。
那麼,對於將資料儲存到資料庫中的操作一共就兩種:一種是新增資料的操作,一種是修改資料的操作。
4.1 新增資料
我們,想要新增資料,就需要在序列化器類中定義一個create()方法。
def create(self, validated_data): ''' 序列化器進行新增資料的方法 :param validated_data: 通過驗證的字典資料 :return:根據RESTful設計方式,需要將新增的資料返回 ''' return ORM新增資料的語句(模型類.objects.create(**validated_data))
例如:
def create(self, validated_data): ''' 序列化器進行新增資料的方法 :param validated_data: 通過驗證的字典資料 :return:根據RESTful設計方式,需要將新增的資料返回 ''' return BookInfo.objects.create(**validated_data)
在這裡,我們需要返回新增的資料給前端,因為我們定義的API是遵守RESTful設計風格的。
Shell測試程式碼:
>>> from booktest.serializers import BookInfoSerializer >>> data = {'btitle': 'django手冊', 'bpub_date': '2020-02-05', 'bread': 20, 'bcomment': 10} >>> s = BookInfoSerializer(data=data) >>> s.is_valid() True >>> s.save() <BookInfo: django手冊>
注意:
當我們建立序列化物件時,只傳遞data資料,就表示我們需要向資料庫裡新增資料。
所以,當序列化器物件呼叫save()方法時,會自動呼叫序列化器類中的create()方法。
4.2 修改資料
我們,想要修改資料時,需要在序列化器類中定義一個update()方法。
def update(self, instance, validated_data): ''' 序列化器進行修改資料的方法 :param instance: 需要修改的模型物件 :param validated_data: 前端傳遞的字典資料 :return: 根據RESTful設計方式,需要將修改的資料返回 ''' # 新值覆蓋舊值 instance.欄位名 = validated_data.get(欄位名) instance.save() return instance
例如:
def update(self, instance, validated_data): ''' 序列化器進行修改資料的方法 :param instance: 需要修改的模型物件 :param validated_data: 前端傳遞的字典資料 :return: 根據RESTful設計方式,需要將修改的資料返回 ''' # 新值覆蓋舊值 instance.btitle = validated_data.get('btitle') instance.bpub_date = validated_data.get('bpub_date') instance.bread = validated_data.get('bread') instance.bcomment = validated_data.get('bcomment') instance.save() return instance
我們同樣也需要將修改的資料返回給前端。
Shell測試程式碼:
from booktest.models import BookInfo from booktest.serializers import BookInfoSerializer >>> book = BookInfo.objects.get(id=10) >>> data = {'btitle': 'python_django手冊', 'bpub_date': '2020-02-05', 'bread': 20, 'bcomment': 10} >>> s = BookInfoSerializer(instance=book,data=data) >>> s.is_valid() True >>> s.save() <BookInfo: python_django手冊>
注意:
當我們建立序列化器物件時,傳遞了instance和data資料,就表示我們需要進行資料的修改操作。
所以,當我們使用序列化器物件呼叫save()方法時,會自動呼叫序列化器類中的update()方法。
至此,我們的Serializer序列化的反序列化操作就學習完畢了。
序列化器的學習中,幾乎沒有什麼邏輯點,因為,使用的是他人已經封裝好的框架,所以必須遵守框架的規定來開發,只需要,記住模版即