官方原文連接
本系列文章 github 地址
轉載請註明出處html
Form 類中的每一個字段不只負責驗證數據,還負責 「清洗」 它 — 將其規範化爲一致的格式。python
— Django 文檔git
序列化字段處理基本數據類型和其餘數據類型(好比自定義的類)之間的轉換。它們還能夠對數據進行驗證,以及從其父對象中檢索和設置值。github
注意: 序列化字段都聲明在 fields.py
中,但按照慣例,應該使用 from rest_framework import serializers
,並用 serializers.<FieldName>
的方式引用。正則表達式
每一個序列化字段類的構造函數都須要一些參數。某些字段類須要附加特定於該字段的參數,但應始終接受如下參數:django
read_only
只讀字段包含於輸出 API 中,不該該包含在須要建立或更新操做的輸入 API 中。在序列化類輸入中錯誤的包含 'read_only' 會被忽略。api
將其設置爲 True
可確保在序列化表示時使用該字段,但在反序列化期間建立或更新實例時不使用該字段。bash
默認爲 False
數據結構
write_only
將其設置爲 True
以確保在更新或建立實例時可使用該字段,但在序列化表示時不包括該字段。ide
默認爲 False
required
若是在反序列化過程當中沒有該提供字段,一般會出現錯誤。若是在反序列化過程當中不須要此字段,則應該設置爲 false。
將此設置爲 False
還容許在序列化實例時從輸出中省略對象屬性或字典密鑰。若是密鑰不存在,它將不會包含在輸出表示中。
默認爲 True
allow_null
若是把 None
傳遞給序列化字段,一般會引起錯誤。若是 None
應被視爲有效值,則將此關鍵字參數設置爲 True
。
請注意,將此參數設置爲 True
將意味着序列化輸出的缺省值爲 null
,但並不意味着輸入反序列化的缺省值。
默認爲 False
default
若是設置,則會給出默認值,在沒有提供輸入值時,將使用該默認值。若是未設置,則默認行爲是不填充該屬性。
部分更新操做時不該該使用 default
。由於有些狀況下,只有傳入數據中提供的字段纔會返回驗證值。
能夠設置爲函數或其餘可調用的對象,在這種狀況下,每次使用該值時都會對其進行調用。被調用時,它將不會收到任何參數。若是可調用對象具備 set_context
方法,那麼在每次將字段實例做爲參數獲取值以前都會調用該方法。這與驗證器的工做方式相同。
在序列化實例時,若是對象屬性或字典關鍵字不存在於實例中,將使用缺省值。
請注意,設置默認值意味着該字段不是必需的。同時包括 default
和 required
的關鍵字參數都是無效的,會引起錯誤。
source
將用於填充字段的屬性的名稱。能夠是一個只接受 self
參數的方法,如 URLField(source='get_absolute_url')
,或者使用點符號來遍歷屬性,如 EmailField(source='user.email')
。在使用點符號時,若是在屬性遍歷期間任何對象不存在或爲空,則可能須要提供缺省值。
source ='*'
具備特殊含義,用於表示整個對象應該傳遞到該字段。這對建立嵌套表示或對於須要訪問完整對象以肯定輸出表示的字段很是有用。
默認爲該字段的名稱。
validators
應該應用於傳入字段輸入的驗證函數列表,該列表中的函數應該引起驗證錯誤或僅返回。驗證器函數一般應該引起 serializers.ValidationError
,但 Django 的內置 ValidationError
也支持與 Django 代碼庫或第三方 Django 包中定義的驗證器兼容。
error_messages
一個字典,key 是錯誤代碼, value 是對應的錯誤信息。
label
一個簡短的文本字符串,可用做 HTML 表單字段或其餘描述性元素中字段的名稱。
help_text
一個文本字符串,可用做 HTML 表單字段或其餘描述性元素中字段的描述。
initial
應該用於預填充 HTML 表單字段的值。你可能會傳遞一個可調用對象,就像你對任何常規 Django Field
所作的同樣:
import datetime
from rest_framework import serializers
class ExampleSerializer(serializers.Serializer):
day = serializers.DateField(initial=datetime.date.today)
複製代碼
style
可用於控制渲染器渲染字段的鍵值對的字典。
這裏有兩個例子是 'input_type'
和 'base_template'
:
# Use <input type="password"> for the input.
password = serializers.CharField(
style={'input_type': 'password'}
)
# Use a radio input instead of a select input.
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'}
)
複製代碼
表示一個 boolean 值。
使用 HTML 編碼表單時須要注意,省略一個 boolean 值被視爲將字段設置爲 False
,即便它指定了 default=True
選項。這是由於 HTML 複選框經過省略該值來表示未選中的狀態,因此 REST framework 將省略看做是空的複選框。
請注意,將使用 required=False
選項生成默認的 BooleanField
實例(由於 Django models.BooleanField
始終爲 blank=True
)。若是想要更改此行爲,請在序列化類上顯式聲明 BooleanField
。
對應與 django.db.models.fields.BooleanField
.
簽名: BooleanField()
表示一個布爾值,它也接受 None
做爲有效值。
對應與 django.db.models.fields.NullBooleanField
.
簽名: NullBooleanField()
表示文本。可使用 max_length
, min_length
驗證(或限定)文本的長短。
對應與 django.db.models.fields.CharField
或 django.db.models.fields.TextField
.
簽名: CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
max_length
- 驗證輸入所包含的字符數不超過這個數目。min_length
- 驗證輸入所包含的字符數很多於這個數目。allow_blank
- 若是設置爲 True
,則空字符串應被視爲有效值。若是設置爲 False
,那麼空字符串被認爲是無效的並會引起驗證錯誤。默認爲 False
。trim_whitespace
- 若是設置爲 True
,則先後空白將被刪除。默認爲 True
。allow_null
選項也可用於字符串字段,儘管它相對於 allow_blank
來講不被推薦。同時設置 allow_blank=True
和 allow_null=True
是有效的,但這樣作意味着字符串表示容許有兩種不一樣類型的空值,這可能致使數據不一致和微妙的應用程序錯誤。
表示文本,將文本驗證爲有效的電子郵件地址。
對應與 django.db.models.fields.EmailField
簽名: EmailField(max_length=None, min_length=None, allow_blank=False)
表示文本,用於驗證給定的值是否與某個正則表達式匹配。
對應與 django.forms.fields.RegexField
.
簽名: RegexField(regex, max_length=None, min_length=None, allow_blank=False)
強制的 regex
參數能夠是一個字符串,也能夠是一個編譯好的 Python 正則表達式對象。
使用 Django 的 django.core.validators.RegexValidator
進行驗證。
一個根據模式 [a-zA-Z0-9_-]+
驗證輸入的 RegexField
。
對應與 django.db.models.fields.SlugField
.
簽名: SlugField(max_length=50, min_length=None, allow_blank=False)
一個根據 URL 匹配模式驗證輸入的 RegexField
。徹底合格的 URL 格式爲 http://<host>/<path>
。
對應與 django.db.models.fields.URLField
. 使用 Django 的 django.core.validators.URLValidator
進行驗證。
簽名: URLField(max_length=200, min_length=None, allow_blank=False)
確保輸入的字段是有效的 UUID 字符串。to_internal_value
方法將返回一個 uuid.UUID
實例。在輸出時,字段將以規範的連字符格式返回一個字符串,例如:
"de305d54-75b4-431b-adb2-eb6b9e546013"
複製代碼
簽名: UUIDField(format='hex_verbose')
format
: 肯定 uuid 值的表示形式
'hex_verbose'
- 權威的十六進制表示形式,包含連字符: "5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
'hex'
- 緊湊的十六進制表示形式, 不包含連字符:"5ce0e9a55ffa654bcee01238041fb31a"
'int'
- 128 位整數表示形式:"123456789012312313134124512351145145114"
'urn'
- RFC 4122 URN 表示形式: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
修改 format
僅影響表示值。全部格式都被 to_internal_value
接受。一個其選項僅限於文件系統上某個目錄中的文件名的字段。
對應於 django.forms.fields.FilePathField
.
簽名: FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)
path
- FilePathField 應該從中選擇的目錄的絕對文件系統路徑。match
- 用來過濾文件名的正則表達式,string 類型。recursive
- 指定是否應該包含路徑的全部子目錄。默認值是 False
。allow_files
- 是否應該包含指定位置的文件。默認值爲 True
。這個參數或 allow_folders
必須是 True
。(兩個屬性必須有一個爲 true
)allow_folders
- 是否應該包含指定位置的文件夾。默認值是 False
。這個參數或 allow_files
必須是 True
。(兩個屬性必須有一個爲 true
)確保輸入是有效的 IPv4 或 IPv6 字符串。
對應於 django.forms.fields.IPAddressField
和 django.forms.fields.GenericIPAddressField
.
簽名: IPAddressField(protocol='both', unpack_ipv4=False, **options)
protocol
將有效輸入限制爲指定的協議。接受的值是 'both'
(默認),'IPv4'
或 'IPv6'
。匹配不區分大小寫。unpack_ipv4
解壓 IPv4 映射的地址,如 ::ffff:192.0.2.1
。若是啓用此選項,則該地址將解壓到 192.0.2.1。 默認是禁用的。只能在 protocol
設置爲 'both'
時使用。表示整數。
對應於 django.db.models.fields.IntegerField
, django.db.models.fields.SmallIntegerField
, django.db.models.fields.PositiveIntegerField
和 django.db.models.fields.PositiveSmallIntegerField
。
簽名: IntegerField(max_value=None, min_value=None)
max_value
驗證所提供的數字不大於這個值。min_value
驗證所提供的數字不小於這個值。表示浮點。
對應於 django.db.models.fields.FloatField
.
簽名: FloatField(max_value=None, min_value=None)
max_value
驗證所提供的數字不大於這個值。min_value
驗證所提供的數字不小於這個值。表示十進制,由 Python 用 Decimal
實例表示。
對應於 django.db.models.fields.DecimalField
.
簽名: DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits
容許的最大位數。它必須是 None
或大於等於 decimal_places
的整數。decimal_places
小數位數。coerce_to_string
若是應返回字符串值,則設置爲 True
;若是應返回 Decimal
對象,則設置爲 False
。默認值與 COERCE_DECIMAL_TO_STRING
settings key 的值相同,除非被覆蓋,不然該值將爲 True
。若是序列化對象返回 Decimal
對象,則最終的輸出格式將由渲染器決定。請注意,設置 localize
將強制該值爲 True
。max_value
驗證所提供的數字不大於這個值。min_value
驗證所提供的數字不小於這個值。localize
設置爲 True
以啓用基於當前語言環境的輸入和輸出本地化。這也會迫使 coerce_to_string
爲 True
。默認爲 False
。請注意,若是你在 settings 文件中設置了 USE_L10N=True
,則會啓用數據格式化。rounding
設置量化到配置精度時使用的舍入模式。 有效值是 decimal
模塊舍入模式。默認爲 None
。若要驗證數字到999,精確到 2 位小數,應該使用:
serializers.DecimalField(max_digits=5, decimal_places=2)
複製代碼
用10位小數來驗證數字不超過10億:
serializers.DecimalField(max_digits=19, decimal_places=10)
複製代碼
這個字段還接受一個可選參數,coerce_to_string
。若是設置爲 True
,則表示將以字符串形式輸出。若是設置爲 False
,則表示將保留爲 Decimal
實例,最終表示形式將由渲染器肯定。
若是未設置,則默認設置爲與 COERCE_DECIMAL_TO_STRING
setting 相同的值,除非另行設置,不然該值爲 True
。
表示日期和時間。
對應於 django.db.models.fields.DateTimeField
.
簽名: DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
format
- 表示輸出格式的字符串。若是未指定,則默認爲與 DATETIME_FORMAT
settings key 相同的值,除非設置,不然將爲 'iso-8601'
。設置爲格式化字符串則代表 to_representation
返回值應該被強制爲字符串輸出。格式化字符串以下所述。將此值設置爲 None
表示 Python datetime
對象應由 to_representation
返回。在這種狀況下,日期時間編碼將由渲染器肯定。input_formats
- 表示可用於解析日期的輸入格式的字符串列表。 若是未指定,則將使用 DATETIME_INPUT_FORMATS
設置,該設置默認爲 ['iso-8601']
。DateTimeField
格式化字符串。格式化字符串能夠是明確指定的 Python strftime 格式,也能夠是使用 ISO 8601 風格 datetime 的特殊字符串 iso-8601
。(例如 '2013-01-29T12:34:56.000000Z'
)
當一個 None
值被用於格式化 datetime
對象時,to_representation
將返回,最終的輸出表示將由渲染器類決定。
auto_now
和 auto_now_add
模型字段。使用 ModelSerializer
或 HyperlinkedModelSerializer
時,請注意,auto_now=True
或 auto_now_add=True
的模型字段默認狀況下將使用 read_only=True
。
若是想覆蓋此行爲,則須要在序列化類中明確聲明 DateTimeField
。例如:
class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
class Meta:
model = Comment
複製代碼
表示日期。
對應於 django.db.models.fields.DateField
簽名: DateField(format=api_settings.DATE_FORMAT, input_formats=None)
format
- 表示輸出格式的字符串。若是未指定,則默認爲與 DATE_FORMAT
settings key 相同的值,除非設置,不然將爲 'iso-8601'
。設置爲格式化字符串則代表 to_representation
返回值應該被強制爲字符串輸出。格式化字符串以下所述。將此值設置爲 None
表示 Python date
對象應由 to_representation
返回。在這種狀況下,日期時間編碼將由渲染器肯定。input_formats
- 表示可用於解析日期的輸入格式的字符串列表。 若是未指定,則將使用 DATE_INPUT_FORMATS
設置,該設置默認爲 ['iso-8601']
。DateField
格式化字符串格式化字符串能夠是明確指定的 Python strftime 格式,也能夠是使用 ISO 8601 風格 date 的特殊字符串 iso-8601
。(例如 '2013-01-29'
)
表示時間。
對應於 django.db.models.fields.TimeField
簽名: TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
format
- 表示輸出格式的字符串。若是未指定,則默認爲與 TIME_FORMAT
settings key 相同的值,除非設置,不然將爲 'iso-8601'
。設置爲格式化字符串則代表 to_representation
返回值應該被強制爲字符串輸出。格式化字符串以下所述。將此值設置爲 None
表示 Python time
對象應由 to_representation
返回。在這種狀況下,日期時間編碼將由渲染器肯定。input_formats
- 表示可用於解析日期的輸入格式的字符串列表。 若是未指定,則將使用 TIME_INPUT_FORMATS
設置,該設置默認爲 ['iso-8601']
。TimeField
格式化字符串格式化字符串能夠是明確指定的 Python strftime 格式,也能夠是使用 ISO 8601 風格 time 的特殊字符串 iso-8601
。(例如 '12:34:56.000000'
)
表示持續時間。 對應於 django.db.models.fields.DurationField
這些字段的 validated_data
將包含一個 datetime.timedelta
實例。該表示形式是遵循格式 '[DD] [HH:[MM:]]ss[.uuuuuu]'
的字符串。
簽名: DurationField()
能夠從一個有限的選擇中接受值的字段。
若是相應的模型字段包含 choices=…
參數,則由 ModelSerializer
自動生成字段。
簽名: ChoiceField(choices)
choices
- 有效值列表,或 (key, display_name)
元組列表。allow_blank
- 若是設置爲 True
,則空字符串應被視爲有效值。若是設置爲 False
,那麼空字符串被認爲是無效的並會引起驗證錯誤。默認是 False
。html_cutoff
- 若是設置,這將是 HTML 選擇下拉菜單中顯示的選項的最大數量。可用於確保自動生成具備很是大能夠選擇的 ChoiceField,而不會阻止模板的渲染。默認是 None
.html_cutoff_text
- 指定一個文本指示器,在截斷列表時顯示,好比在 HTML 選擇下拉菜單中已經截斷了最大數量的項目。默認就會顯示 "More than {count} items…"
Allow_blank
和 allow_null
都是 ChoiceField
上的有效選項,但強烈建議只使用一個而不是兩個都用。對於文本選擇,allow_blank
應該是首選,allow_null
應該是數字或其餘非文本選項的首選。
能夠接受一組零、一個或多個值的字段,從有限的一組選擇中選擇。採起一個必填的參數。 to_internal_value
返回一個包含選定值的 set
。
簽名: MultipleChoiceField(choices)
choices
- 有效值列表,或 (key, display_name)
元組列表。allow_blank
- 若是設置爲 True
,則空字符串應被視爲有效值。若是設置爲 False
,那麼空字符串被認爲是無效的並會引起驗證錯誤。默認是 False
。html_cutoff
- 若是設置,這將是 HTML 選擇下拉菜單中顯示的選項的最大數量。可用於確保自動生成具備很是大能夠選擇的 ChoiceField,而不會阻止模板的渲染。默認是 None
.html_cutoff_text
- 指定一個文本指示器,在截斷列表時顯示,好比在 HTML 選擇下拉菜單中已經截斷了最大數量的項目。默認就會顯示 "More than {count} items…"
Allow_blank
和 allow_null
都是 ChoiceField
上的有效選項,但強烈建議只使用一個而不是兩個都用。對於文本選擇,allow_blank
應該是首選,allow_null
應該是數字或其餘非文本選項的首選。
FileField
和 ImageField
類只適用於 MultiPartParser
或 FileUploadParser
。大多數解析器,例如, e.g. JSON 不支持文件上傳。 Django 的常規 FILE_UPLOAD_HANDLERS
用於處理上傳的文件。
表示文件。執行 Django 的標準 FileField 驗證。
對應於 django.forms.fields.FileField
.
簽名: FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
max_length
- 指定文件名的最大長度。allow_empty_file
- 指定是否容許空文件。use_url
- 若是設置爲 True
,則 URL 字符串值將用於輸出表示。若是設置爲 False
,則文件名字符串值將用於輸出表示。默認爲 UPLOADED_FILES_USE_URL
settings key 的值,除非另有設置,不然爲 True
。表示圖片。驗證上傳的文件內容是否匹配已知的圖片格式。
對應於 django.forms.fields.ImageField
.
簽名: ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
max_length
- 指定文件名的最大長度。allow_empty_file
- 指定是否容許空文件。use_url
- 若是設置爲 True
,則 URL 字符串值將用於輸出表示。若是設置爲 False
,則文件名字符串值將用於輸出表示。默認爲 UPLOADED_FILES_USE_URL
settings key 的值,除非另有設置,不然爲 True
。須要 Pillow
庫或 PIL
庫。 建議使用 Pillow
庫。 由於 PIL
已經再也不維護。
驗證對象列表的字段類。
簽名: ListField(child=<A_FIELD_INSTANCE>, min_length=None, max_length=None)
child
- 應該用於驗證列表中的對象的字段實例。若是未提供此參數,則列表中的對象將不會被驗證。min_length
- 驗證列表中包含的元素數量很多於這個數。max_length
- 驗證列表中包含的元素數量不超過這個數。例如,要驗證整數列表:
scores = serializers.ListField(
child=serializers.IntegerField(min_value=0, max_value=100)
)
複製代碼
ListField
類還支持一種聲明式風格,容許編寫可重用的列表字段類。
class StringListField(serializers.ListField):
child = serializers.CharField()
複製代碼
咱們如今能夠在咱們的應用程序中從新使用咱們自定義的 StringListField
類,而無需爲其提供 child
參數。
驗證對象字典的字段類。DictField
中的鍵老是被假定爲字符串值。
簽名: DictField(child=<A_FIELD_INSTANCE>)
child
- 應該用於驗證字典中的值的字段實例。若是未提供此參數,則映射中的值將不會被驗證。例如,要建立一個驗證字符串到字符串映射的字段,能夠這樣寫:
document = DictField(child=CharField())
複製代碼
你也能夠像使用 ListField
同樣使用聲明式風格。例如:
class DocumentField(DictField):
child = CharField()
複製代碼
驗證傳入的數據結構由有效 JSON 基元組成的字段類。在其二進制模式下,它將表示並驗證 JSON 編碼的二進制字符串。
簽名: JSONField(binary)
binary
- 若是設置爲 True
,那麼該字段將輸出並驗證 JSON 編碼的字符串,而不是原始數據結構。默認是 False
.只是簡單地返回字段的值而不進行修改的字段類。
當包含與屬性相關的字段名而不是模型字段時,此字段默認與 ModelSerializer
一塊兒使用。
簽名: ReadOnlyField()
例如,若是 has_expired
是 Account
模型中的一個屬性,則如下序列化程序會自動將其生成爲 ReadOnlyField
:
class AccountSerializer(serializers.ModelSerializer):
class Meta:
model = Account
fields = ('id', 'account_name', 'has_expired')
複製代碼
不根據用戶輸入獲取值的字段類,而是從默認值或可調用值中獲取值。
簽名: HiddenField()
例如,要包含始終提供當前時間的字段做爲序列化類驗證數據的一部分,則可使用如下內容:
modified = serializers.HiddenField(default=timezone.now)
複製代碼
若是須要根據某些預先提供的字段值運行某些驗證,則一般只須要 HiddenField
類,而不是將全部這些字段公開給最終用戶。
能夠綁定到任意模型字段的通用字段。ModelField
類將序列化/反序列化的任務委託給其關聯的模型字段。該字段可用於爲自定義模型字段建立序列化字段,而無需建立新的自定義序列化字段。
ModelSerializer
使用此字段來對應自定義模型字段類。
簽名: ModelField(model_field=<Django ModelField instance>)
ModelField
類一般用於內部使用,但若是須要,能夠由 API 使用。爲了正確實例化 ModelField
,必須傳遞一個附加到實例化模型的字段。例如:ModelField(model_field=MyModel()._meta.get_field('custom_field'))
這是一個只讀字段。它經過調用它所鏈接的序列化類的方法來得到它的值。它可用於將任何類型的數據添加到對象的序列化表示中。
簽名: SerializerMethodField(method_name=None)
method_name
- 要調用序列化對象的方法的名稱。若是不包含,則默認爲 get_<field_name>
.由 method_name
參數引用的序列化方法應該接受一個參數(除了 self
),這是要序列化的對象。它應該返回你想要包含在對象的序列化表示中的任何內容。例如:
from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers
class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
class Meta:
model = User
def get_days_since_joined(self, obj):
return (now() - obj.date_joined).days
複製代碼
若是你想建立自定義字段,則須要對 Field
進行子類化,而後重寫 .to_representation()
和 .to_internal_value()
方法中的一個或兩個。這兩個方法用於在初始數據類型和基本序列化數據類型之間進行轉換。基本數據類型一般是 number,string, boolean, date
/time
/datetime
或 None
。它們也能夠是任何僅包含其餘基本對象的列表或字典。其餘類型可能會支持,但具體取決於你使用的渲染器。
調用 .to_representation()
方法將初始數據類型轉換爲基本的可序列化數據類型。
調用 to_internal_value()
方法將基本數據類型恢復爲其內部 python 表示形式。若是數據無效,此方法應該引起 serializers.ValidationError
異常。
請注意,2.x 版本中存在的 WritableField
類再也不存在。 應此,若是字段須要支持數據輸入,則應該繼承 Field
並覆蓋 to_internal_value()
。
咱們來看一個序列化表明 RGB 顏色值的類的例子:
class Color(object):
""" A color represented in the RGB colorspace. """
def __init__(self, red, green, blue):
assert(red >= 0 and green >= 0 and blue >= 0)
assert(red < 256 and green < 256 and blue < 256)
self.red, self.green, self.blue = red, green, blue
class ColorField(serializers.Field):
""" Color objects are serialized into 'rgb(#, #, #)' notation. """
def to_representation(self, obj):
return "rgb(%d, %d, %d)" % (obj.red, obj.green, obj.blue)
def to_internal_value(self, data):
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
return Color(red, green, blue)
複製代碼
默認狀況下,字段值被視爲映射到對象的屬性。若是須要自定義字段值的訪問方式,則須要覆蓋 .get_attribute()
和/或 .get_value()
。
讓咱們建立一個能夠用來表示被序列化對象的類名的字段:
class ClassNameField(serializers.Field):
def get_attribute(self, obj):
# We pass the object instance onto `to_representation`,
# not just the field attribute.
return obj
def to_representation(self, obj):
""" Serialize the object's class name. """
return obj.__class__.__name__
複製代碼
咱們上面的 ColorField
類目前不執行任何數據驗證。爲了表示無效數據,咱們應該引起一個 serializers.ValidationError
,以下所示:
def to_internal_value(self, data):
if not isinstance(data, six.text_type):
msg = 'Incorrect type. Expected a string, but got %s'
raise ValidationError(msg % type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
raise ValidationError('Incorrect format. Expected `rgb(#,#,#)`.')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
raise ValidationError('Value out of range. Must be between 0 and 255.')
return Color(red, green, blue)
複製代碼
.fail()
方法是引起 ValidationError
的快捷方式,它從 error_messages
字典中接收消息字符串。例如:
default_error_messages = {
'incorrect_type': 'Incorrect type. Expected a string, but got {input_type}',
'incorrect_format': 'Incorrect format. Expected `rgb(#,#,#)`.',
'out_of_range': 'Value out of range. Must be between 0 and 255.'
}
def to_internal_value(self, data):
if not isinstance(data, six.text_type):
self.fail('incorrect_type', input_type=type(data).__name__)
if not re.match(r'^rgb\([0-9]+,[0-9]+,[0-9]+\)$', data):
self.fail('incorrect_format')
data = data.strip('rgb(').rstrip(')')
red, green, blue = [int(col) for col in data.split(',')]
if any([col > 255 or col < 0 for col in (red, green, blue)]):
self.fail('out_of_range')
return Color(red, green, blue)
複製代碼
這種風格讓你的錯誤信息更清晰,而且與代碼分離,應該是首選。
source='*'
這裏咱們將舉一個具備 x_coordinate
和 y_coordinate
屬性的平面 DataPoint
模型的示例。
class DataPoint(models.Model):
label = models.CharField(max_length=50)
x_coordinate = models.SmallIntegerField()
y_coordinate = models.SmallIntegerField()
複製代碼
使用自定義字段和 source ='*'
,咱們能夠提供座標對的嵌套表示形式:
class CoordinateField(serializers.Field):
def to_representation(self, obj):
ret = {
"x": obj.x_coordinate,
"y": obj.y_coordinate
}
return ret
def to_internal_value(self, data):
ret = {
"x_coordinate": data["x"],
"y_coordinate": data["y"],
}
return ret
class DataPointSerializer(serializers.ModelSerializer):
coordinates = CoordinateField(source='*')
class Meta:
model = DataPoint
fields = ['label', 'coordinates']
複製代碼
請注意,此示例不處理驗證。使用 source ='*'
的嵌套序列化類能夠更好地處理座標嵌套,而且帶有兩個 IntegerField
實例,每一個實例都有本身的 source
指向相關字段。
然而,這個例子的關鍵點是:
to_representation
傳遞整個 DataPoint
對象, 而且會映射到所需的輸出。>>> instance = DataPoint(label='Example', x_coordinate=1, y_coordinate=2)
>>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data
ReturnDict([('label', 'Example'), ('coordinates', {'x': 1, 'y': 2})])
複製代碼
to_internal_value
必須映射回適合更新目標對象的字典。使用 source='*'
,to_internal_value
的返回將更新根驗證的數據字典,而不是單個鍵。>>> data = {
... "label": "Second Example",
... "coordinates": {
... "x": 3,
... "y": 4,
... }
... }
>>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid()
True
>>> in_serializer.validated_data
OrderedDict([('label', 'Second Example'),
('y_coordinate', 4),
('x_coordinate', 3)])
複製代碼
爲了完整性,咱們再次作一樣的事情,可是使用上面建議的嵌套序列化方法:
class NestedCoordinateSerializer(serializers.Serializer):
x = serializers.IntegerField(source='x_coordinate')
y = serializers.IntegerField(source='y_coordinate')
class DataPointSerializer(serializers.ModelSerializer):
coordinates = NestedCoordinateSerializer(source='*')
class Meta:
model = DataPoint
fields = ['label', 'coordinates']
複製代碼
這裏,咱們在 IntegerField
聲明中處理目標和源屬性對(x
和 x_coordinate
,y
和 y_coordinate
)之間的映射。這是使用了 source ='*'
的 NestedCoordinateSerializer
。
新的 DataPointSerializer
展示出與自定義字段方法相同的行爲。
序列化:
>>> out_serializer = DataPointSerializer(instance)
>>> out_serializer.data
ReturnDict([('label', 'testing'),
('coordinates', OrderedDict([('x', 1), ('y', 2)]))])
複製代碼
反序列化:
>>> in_serializer = DataPointSerializer(data=data)
>>> in_serializer.is_valid()
True
>>> in_serializer.validated_data
OrderedDict([('label', 'still testing'),
('x_coordinate', 3),
('y_coordinate', 4)])
複製代碼
雖然沒有編寫驗證,可是可使用內置的驗證方式:
>>> invalid_data = {
... "label": "still testing",
... "coordinates": {
... "x": 'a',
... "y": 'b',
... }
... }
>>> invalid_serializer = DataPointSerializer(data=invalid_data)
>>> invalid_serializer.is_valid()
False
>>> invalid_serializer.errors
ReturnDict([('coordinates',
{'x': ['A valid integer is required.'],
'y': ['A valid integer is required.']})])
複製代碼
出於這個緣由,能夠首先嚐試嵌套序列化類方法。當嵌套序列化類變得不可行或過於複雜時,可使用自定義字段方法。