1. 程式人生 > >DRF 序列化器-Serializer (2)

DRF 序列化器-Serializer (2)

exc 使用 ring llb print url model 數據保存 根據

作用

  1. 序列化,序列化器會把模型對象轉換成字典,經過response以後變成json字符串
  2. 完成數據校驗功能
  3. 反序列化,把客戶端發送過來的數據,經過request以後變成字典,序列化器可以把字典轉成模型

準備數據模型類booktest/model.py

class BookInfoSerializer(serializers.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) image = serializers.ImageField(label=圖片, required=False)

一 定義序列化器

  Django REST framework中的Serializer使用類來定義,須繼承rest_framework.serializers.Serializer

  我們為模型類提供一個序列化器.

class BookInfoSerializer(serializers.Serializer):
    """圖書數據序列化器"""
    id = serializers.IntegerField(label=ID, read_only=True) #read_only 僅僅用於讀取數據
    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) image = serializers.ImageField(label=圖片, required=False)

  註意:serializer不是只能為數據庫模型類定義,也可以為非數據庫模型類的數據定義。serializer是獨立於數據庫之外的存在。

二 查詢庫表

常見字段類型

字段字段構造方式
BooleanField BooleanField()
NullBooleanField NullBooleanField()
CharField CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailField EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField RegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugField SlugField(maxlength=50, min_length=None, allow_blank=False) 正則字段,驗證正則模式 [a-zA-Z0-9-]+
URLField URLField(max_length=200, min_length=None, allow_blank=False)
UUIDField UUIDField(format=‘hex_verbose‘) format: 1) ‘hex_verbose‘"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) ‘hex‘"5ce0e9a55ffa654bcee01238041fb31a" 3)‘int‘ - 如: "123456789012312313134124512351145145114" 4)‘urn‘ 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
IPAddressField IPAddressField(protocol=‘both‘, unpack_ipv4=False, **options)
IntegerField IntegerField(max_value=None, min_value=None)
FloatField FloatField(max_value=None, min_value=None)
DecimalField DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位數 decimal_palces: 小數點位置
DateTimeField DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateField DateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeField TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationField DurationField()
ChoiceField ChoiceField(choices) choices與Django的用法相同
MultipleChoiceField MultipleChoiceField(choices)
FileField FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageField ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListField ListField(child=, min_length=None, max_length=None)
DictField DictField(child=)

選項參數

參數名稱作用
max_length 最大長度
min_lenght 最小長度
allow_blank 是否允許為空
trim_whitespace 是否截斷空白字符
max_value 最小值
min_value 最大值

通用參數

參數名稱說明
read_only 表明該字段僅用於序列化輸出,默認False
write_only 表明該字段僅用於反序列化輸入,默認False
required 表明該字段在反序列化時必須輸入,默認True
default 反序列化時使用的默認值
allow_null 表明該字段是否允許傳入None,默認False
validators 該字段使用的驗證器
error_messages 包含錯誤編號與錯誤信息的字典
label 用於HTML展示API頁面時,顯示的字段名稱
help_text 用於HTML展示API頁面時,顯示的字段幫助提示信息

三 創建Serializer對象

  定義好Serializer類後,就可以創建Serializer對象了.

Serializer(instance=None, data=empty, **kwarg)
創建序列化器對象
  • 參數1: instance=要序列化的模型數據
  • 參數2: data=要反序列化器的字典數據
  • 參數3: many= 是否要序列化多個模型數據,多條數據many=True,默認一條數據
  • 參數4: context=序列化器使用的上下文,字典類型數據,可以通過context把視圖中的數據,傳遞給序列化器內部使用

說明:

  1)用於序列化時,將模型類對象傳入instance參數

  2)用於反序列化時,將要被反序列化的數據傳入data參數

  3)除了instance和data參數外,在構造Serializer對象時,還可通過context參數額外添加數據,如

serializer = AccountSerializer(account, context={

      ‘request: request
}) #把數據傳遞給序列器

  通過context參數附加的數據,可以通過Serializer對象的context屬性獲取。

四 序列化器的使用

序列化器的使用分兩個階段:

  1. 在客戶端請求時,使用序列化器可以完成對數據的反序列化。

  2. 在服務器響應時,使用序列化器可以完成對數據的序列化。

五 序列化

  三步驟:

    1 操作數據庫

    2 構造序列化器對象

    3 響應數據

class BookInfoView(View):
    def get(self,request):
        # 操作數據庫
        books = BookInfo.objects.all()
        # 創建序列化器對象
        serializer = BookInfo2Serializer(instance=books,many=True)
        # 通過 serializer.data 獲取序列化完成以後的數據
        print ( serializer.data )
        # 返回數據
        return JsonResponse(serializer.data,safe=False) #safe=Fase 表示跳過嚴格檢驗數據類型是否為dict

  如果要被序列化的是包含多條數據的查詢集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‘)])]

六 反序列化

(1)數據驗證

  使用序列化器進行反序列化時,需要對數據進行驗證後,才能獲取驗證成功的數據或保存成模型類對象。

  在獲取反序列化的數據前,必須調用is_valid()方法進行驗證,驗證成功返回True,否則返回False。

  • 數據校驗的序列器的編寫(字段中編寫校驗規則)
class BookInfo2Serializer(serializers.Serializer):
    # 自定義要反序列化的字段
    id = serializers.IntegerField(label="主鍵ID",read_only=True)
    btitle = serializers.CharField(label="標題",required=True,min_length=1,max_length=20,validators=[check_btitle])
    bpub_date=serializers.DateField(label="出版日期")
    bread=serializers.IntegerField(label="閱讀量",min_value=0)
    bcomment=serializers.IntegerField(label="評論量",default=0)
    # required=False 反序列化時, 當前字段可以不填
    is_delete=serializers.BooleanField(label="邏輯刪除")

  • 自定義驗證方法
    def validate_btitle(self,data):
        # 例如,圖書名不能是紅樓夢
        if data=="紅樓夢":
            # 拋出錯誤
            raise serializers.ValidationError("紅樓夢是禁書~")
        # 驗證方法中,把數據值必須返回給字段,否則字段值為空
        return data
# 自定義驗證方法[驗證多個或者所有字段,只能出現一次] def validate(self,data): # data 這個是所有字段的內容,字典類型 bread = data.get("bread") bcomment = data.get("bcomment") if bread>=bcomment: return data raise serializers.ValidationError("閱讀量小於評論量,數據太假了") def create(self,validated_data): """保存數據,把字典轉換成模型 validated_data 客戶端提交過來,並經過驗證的數據 """ instance = BookInfo.objects.create( btitle = validated_data.get("btitle"), bread = validated_data.get("bread"), bcomment = validated_data.get("bcomment"), bpub_date = validated_data.get("bpub_date"), is_delete = validated_data.get("is_delete"), )

註意:

1    驗證單個字段,可以有多個方法
2    def validate_<字段名>(self,data): # data當前字段對應的值
3    驗證多個或者所有字段,只能出現一次

(2)反序列化-數據保存view視圖

  前面的驗證數據成功後,我們可以使用序列化器來完成數據反序列化的過程.這個過程可以把數據轉成模型類對象.

from django.views import View
from django.http import QueryDict
from .serializers import BookInfo2Serializer
class BookInfo2View(View):
    def post(self,request):
        """添加一本圖書"""
        # 接受數據
        data = request.POST
        # 反序列化
        serializer = BookInfo2Serializer(data=data)
        # 1. 驗證數據
        # raise_exception=True 把驗證的錯誤信息返回給客戶端,同時阻止程序繼續往下執行
        serializer.is_valid(raise_exception=True)
        # is_valid調用驗證方式: 字段選項validators->自定義驗證方法[單字段]->自定義驗證方法[多字段]
        # 驗證成功後的數據
        # print(serializer.validated_data)
        # 2. 轉換數據成模型,同步到數據庫中
        result = serializer.save() # save會自動調用序列化器類裏面聲明的create/update方法,返回值是當前新增/更新的模型對象

        # 響應數據
        return JsonResponse(serializer.data)

    def put(self,request,pk):
        """更新一個圖書"""
        # 根據id主鍵獲取指定圖書信息
        book = BookInfo.objects.get(pk=pk)
   
        # 獲取put數據
        data = QueryDict(request.body)

        # 使用序列化器完成驗證和反序列化過程
        # partial=False接下裏在反序列化中允許部分數據更新
        serializer = BookInfo2Serializer(instance=book,data=data,partial=False
) serializer.is_valid(raise_exception=True) serializer.save() # 響應數據 return JsonResponse(serializer.data)

註意:

save之所以可以自動識別,什麽時候執行create ,什麽時候執行update
        主要是看創建序列化器對象時,是否有傳入instance參數,
        有instance參數,則save會調用序列化器內部的update方法
        沒有instance參數,則save會調用序列化器內部的create方法

七 超級版序列化器(ModelSerializer)

serializers.py
from rest_framework import serializers
from booktest.models import BookInfo
class BookInfoModelSerializer(serializers.ModelSerializer):
    # 模型序列化器也可以自定義驗證字段[當某些數據不存在於數據庫時,但是需要前端提交過來的,可以進行自定義,
    # 例如,驗證碼,確認密碼]

    class Meta:
        model=BookInfo
        fields = ["id","btitle"]
        # 可以給模型序列化器裏面指定的字段設置限制選項
        extra_kwargs = {
            "bread":{"min_length":0,"required":True},
        }

    # 自定義驗證方法[驗證單個字段,可以有多個方法]
    # def validate_<字段名>(self,data): # data當前字段對應的值
    def validate_btitle(self,data):
        # 例如,圖書名不能是紅樓夢
        if data=="紅樓夢":
            # 拋出錯誤
            raise serializers.ValidationError("紅樓夢是禁書~")
        # 驗證方法中,把數據值必須返回給字段,否則字段值為空
        return data

    # 自定義驗證方法[驗證多個或者所有字段,只能出現一次]
    def validate(self,data): # data 這個是所有字段的內容,字典類型
        bread = data.get("bread")
        bcomment = data.get("bcomment")

        if bread>=bcomment:
            return data
        raise serializers.ValidationError("閱讀量小於評論量,數據太假了")

views.py

###############################################################################################################################
# 3 模型序列化器
# 1. 可以幫我們自動完成字段的聲明[主要是從模型中的字段聲明裏面提取過來]
# 2. 模型序列化器也可以幫我們聲明了create和update方法的代碼
###############################################################################################################################
from django.views import View
from django.http import JsonResponse
from .serializers import BookInfoModelSerializer
class BookInfo3View(View):
    def post(self,request):
        """添加一本圖書"""
        # 接受數據
        data = request.POST
        # 反序列化
        serializer = BookInfoModelSerializer(data=data)
        serializer.is_valid(raise_exception=True)
        result = serializer.save()
        # 響應數據
        return JsonResponse(serializer.data)

    def put(self,request,pk):
        """更新一個圖書"""
        book = BookInfo.objects.get(pk=pk)

        # 獲取put提交的數據
        data = QueryDict(request.body)

        serializer = BookInfoModelSerializer(instance=book,data=data,partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 響應數據
        return JsonResponse(serializer.data)

DRF 序列化器-Serializer (2)