Form 類中的每個字段不僅負責驗證數據,而且還負責“清理”它 — 將其規范化為一致的格式。—— Django 文檔
序列化器字段處理原始值和內部數據類型之間的轉換。它們還處理驗證輸入值,以及從父對象檢索和設置值。
注意: 序列化器字段都聲明在 fields.py
中,但按照慣例,應該使用 from rest_framework import serializers
導入它們,並引用字段作為 serializers.<FieldName>
。
核心參數 (Core arguments)
每個序列化器字段類構造函數至少采用這些參數。某些 Field 類采用附加的、字段特定的參數,但應始終接受以下內容:
read_only
只讀字段包含在 API 輸出中,但不應包含在創建或更新操作期間的輸入中。任何不正確地包含在序列化器輸入中的 'read_only' 字段將被忽略。
將此屬性設置為 True
可確保在序列化表示時使用該字段,但在反序列化期間創建或更新實例時不使用該字段。
默認為 False
write_only
將此屬性設置為 True
可確保在更新或創建實例時可以使用該字段,但在序列化表示時不包括該字段。
默認為 False
required
通常,如果在反序列化期間未提供字段,則會引發錯誤。如果在反序列化期間不需要此字段,則設置為 false。
將此屬性設置為 False
還允許在序列化實例時從輸出中省略對象屬性或字典鍵。如果鍵不存在,它就不會包含在輸出表示中。
默認為 True
default
如果設置,則給出默認值,如果未提供輸入值,將使用該字段。如果未設置,則默認行為是不填充該屬性。
部分更新操作時不應用 default
。在部分更新的情況下,只有傳入數據中提供的字段將返回驗證值。
可以設置為函數或其他可調用函數,在這種情況下,將在每次使用時評估該值。調用時,它不會收到任何參數。如果可調用函數具有 set_context
方法,那么每次在獲取字段實例作為唯一參數的值之前都會調用該方法。這與驗證器的工作方式相同。
序列化實例時,如果實例中不存在對象屬性或字典鍵,則將使用默認值。
請注意,設置默認值意味着該字段不是必須的。同時包括 default
和 required
的關鍵字參數都是無效的,並且會引發錯誤。
allow_null
如果把 None
傳遞給序列化器字段,通常會引發錯誤。如果 None
應被視為有效值,則將此關鍵字參數設置為 True
。
請注意,如果沒有顯式的默認值,將此參數設置為 True
將意味着將序列化輸出的 default
為 null
,但並不表示輸入反序列化的默認值。
默認為 False
source
將用於填充字段的屬性的名稱。可能是只接受 self
參數的方法,如 URLField(source='get_absolute_url')
,或者使用點符號來遍歷屬性,如 EmailField(source='user.email')
。在使用點符號時,如果在屬性遍歷期間任何對象不存在或為空,則可能需要提供 default
值。
source='*'
具有特殊含義,用於指示整個對象應該被傳遞到該字段。這對於創建嵌套表示或需要訪問整個對象以確定輸出表示的字段很有用。
默認為字段名稱。
validators
應用於傳入字段輸入的驗證器函數列表,並且會引發驗證錯誤或僅返回。驗證器函數通常引發 serializers.ValidationError
,但 Django 的內置 ValidationError
也支持與 Django 代碼庫或第三方 Django 包中定義的驗證器兼容。
error_messages
錯誤代碼為鍵,錯誤消息為值的字典。
label
一個簡短的文本字符串,可用作 HTML 表單字段或其他描述性元素中字段的名稱。
help_text
一個文本字符串,可用作 HTML 表單字段或其他描述性元素中字段的描述。
initial
用於預填充 HTML 表單字段值的值。您可以將 callable 傳遞給它,就像使用任何常規 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'
:
# 使用 <input type="password"> 作為輸入。
password = serializers.CharField( style={'input_type': 'password'} ) # 使用單選輸入而不是選擇輸入。 color_channel = serializers.ChoiceField( choices=['red', 'green', 'blue'], style={'base_template': 'radio.html'} )
有關更多詳細信息,請參閱 HTML 和表單文檔。
Boolean 字段 (Boolean fields)
BooleanField
布爾表示。
當使用 HTML 編碼表單輸入時,注意省略總是被視為將字段設置為 False
的值,即使它指定了 default=True
選項。這是因為 HTML 復選框通過省略該值來表示未選中的狀態,所以 REST framework 將省略看作是空的復選框輸入。
注意,默認的 BooleanField
實例將使用 required=False
選項生成 (因為 Django models.BooleanField
始終為 blank=True
)。如果想要更改此行為,請在序列化器類上顯式聲明 BooleanField
。
對應於 django.db.models.fields.BooleanField
。
簽名:BooleanField()
NullBooleanField
還接受 None
作為有效值的布爾表示。
對應於 django.db.models.fields.NullBooleanField
。
簽名:NullBooleanField()
字符串字段 (String fields)
CharField
文本表示。(可選) 驗證文本是否小於 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
是有效的,但這樣做意味着字符串表示允許有兩種不同類型的空值,這可能導致數據不一致和微妙的應用程序錯誤。
EmailField
文本表示,將文本驗證為有效的電子郵件地址。
對應於 django.db.models.fields.EmailField
簽名:EmailField(max_length=None, min_length=None, allow_blank=False)
RegexField
文本表示,用於驗證給定的值是否與某個正則表達式匹配。
對應於 django.forms.fields.RegexField
簽名:RegexField(regex, max_length=None, min_length=None, allow_blank=False)
強制的 regex
參數可以是字符串,也可以是編譯的 python 正則表達式對象。
使用 Django 的 django.core.validators.RegexValidator
進行驗證。
SlugField
根據模式 [a-zA-Z0-9_-]+
驗證輸入的 RegexField
。
對應於 django.db.models.fields.SlugField
簽名:SlugField(max_length=50, min_length=None, allow_blank=False)
URLField
根據 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)
UUIDField
確保輸入是有效 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'
—— UUID 的緊湊的十六進制表示, 不包含連字符:"5ce0e9a55ffa654bcee01238041fb31a"
'int'
—— UUID 的 128 位整數表示:"123456789012312313134124512351145145114"
'urn'
—— UUID 的 RFC 4122 URN 表示:"urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a"
修改format
參數只影響表示值。to_internal_value
接受所有格式。
FilePathField
選擇限於文件系統上某個目錄中的文件名的字段。
應用於 django.forms.fields.FilePathField
。
簽名:FilePathField(path, match=None, recursive=False, allow_files=True, allow_folders=False, required=None, **kwargs)
path
—— FilePathField 應該從中選擇的文件系統到目錄的絕對路徑。match
—— 一個正則表達式,作為字符串,FilePathField 將用於過濾文件名。recursive
—— 指定是否應該包含路徑的所有子目錄。默認值是False
。allow_files
—— 指定是否應該包含指定位置的文件。默認值為True
。這個參數或allow_folders
必須是True
。allow_folders
—— 指定是否應該包含指定位置的文件夾。默認值是False
。這個參數或allow_files
必須是True
。
IPAddressField
確保輸入是有效 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' 時使用。
數字字段 (Numeric fields)
IntegerField
整數表示。
對應於 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
驗證所提供的數字不小於這個值。
FloatField
浮點表示。
對應於 django.db.models.fields.FloatField
。
簽名:FloatField(max_value=None, min_value=None)
max_value
驗證所提供的數字不大於這個值。min_value
驗證所提供的數字不小於這個值。
DecimalField
十進制表示,由 Decimal
實例在 Python 中表示。
對應於 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
設置中的鍵值相同,除非重寫,否則將為True
。如果序列化器返回Decimal
對象,則最終輸出格式將由渲染器確定。請注意,設置localize
會將值強制為True
。max_value
驗證所提供的數字不大於這個值。min_value
驗證所提供的數字不小於這個值。localize
設置為True
以便基於當前區域啟用輸入和輸出本地化。這也將強制coerce_to_string
為True
。默認為False
。請注意,如果在設置文件中設置了USE_L10N = True
,則會啟用數據格式化。rounding
設置量化到配置精度時使用的舍入模式。有效值是decimal
模塊舍入模式。默認為None
。
用法示例 (Example usage)
要使用 2 位小數的精度驗證最大為 999 的數字,您可以使用:
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
設置相同的值,除非另行設置,否則該值為 True
。
日期和時間字段 (Date and time fields)
DateTimeField
日期和時間表示。
對應於 django.db.models.fields.DateTimeField
。
簽名:DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
format
—— 表示輸出格式的字符串。如果未指定,則默認為與DATETIME_FORMAT
設置鍵相同的值,除非設置,否則將為'iso-8601'
。設置為格式字符串表明to_representation
返回值應該被強制為字符串輸出。格式字符串描述如下。將此值設置為None
表明應由to_representation
返回 Pythondatetime
對象。在這種情況下,日期時間編碼將由渲染器確定。input_formats
—— 表示可用於解析日期的輸入格式的字符串列表。如果未指定,則將使用DATETIME_INPUT_FORMATS
設置,默認為['iso-8601']
。
DateTimeField
格式字符串。
格式化字符串可以是顯式指定的 Python strftime 格式,也可以是表明使用 ISO 8601 樣式的日期時間的特殊字符串 iso-8601
。(例如 '2013-01-29T12:34:56.000000Z'
)
當格式化日期時間對象使用 None
值時,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
DateField
日期表示。
對應於 django.db.models.fields.DateField
簽名:DateField(format=api_settings.DATE_FORMAT, input_formats=None)
format
—— 表示輸出格式的字符串。如果未指定,則默認與DATE_FORMAT
設置的鍵相同的值,除非設置,否則將為'iso-8601'
。設置為格式化字符串則表明to_representation
返回值應被強制為字符串輸出。格式化字符串描述如下。將此值設置為None
表示 Pythondate
對象應由to_representation
返回。在這種情況下,日期編碼將由渲染器確定。input_formats
—— 表示可用於解析日期的輸入格式的字符串列表。如果未指定,將使用DATE_INPUT_FORMATS
設置,默認為['iso-8601']
。
DateField
格式化字符串
格式化字符串可以是顯式指定的 Python strftime 格式,也可以是表明使用 ISO 8601 樣式的日期的特殊字符串 iso-8601
。(例如 '2013-01-29'
)
TimeField
時間表示。
對應於 django.db.models.fields.TimeField
簽名:TimeField(format=api_settings.TIME_FORMAT, input_formats=None)
-
format
—— 表示輸出格式的字符串。如果未指定,則默認與TIME_FORMAT
設置的鍵相同的值,除非設置,否則將為'iso-8601'
。設置為格式化字符串則表明to_representation
返回值應被強制為字符串輸出。格式化字符串描述如下。將此值設置為None
表示 Pythontime
對象應由to_representation
返回。在這種情況下,日期編碼將由渲染器確定。
input_formats
—— 表示可用於解析日期的輸入格式的字符串列表。如果未指定,將使用TIME_INPUT_FORMATS
設置,默認為['iso-8601']
。
TimeField
格式化字符串
格式化字符串可以是顯式指定的 Python strftime 格式,也可以是表明使用 ISO 8601 樣式的日期的特殊字符串 iso-8601
。(例如 '12:34:56.000000'
)
DurationField
持續時間表示。對應於 django.db.models.fields.DurationField
這些字段的 validated_data
將包含 datetime.timedelta
實例。該表示形式是遵循格式 '[DD] [HH:[MM:]]ss[.uuuuuu]'
的字符串。
簽名:DurationField()
選擇字段 (Choice selection fields)
ChoiceField
可以接受有限選項集中的值的字段。
如果相應的模型字段包含 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
應該是首選。
MultipleChoiceField
可以接受一組零個、一個或多個值的字段,從一組有限的選選項中選擇。采用一個必填的參數。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…"
與 ChoiceField
一樣,allow_blank
和 allow_null
都是 ChoiceField
選項都是有效的,但強烈建議只使用一個而不是兩個都用。對於文本選擇,allow_blank
應該是首選,而對於數字或其他非文本選擇,allow_null
應該是首選。
文件上傳字段 (File upload fields)
解析器和文件上傳 (Parsers and file uploads.)
FileField
和 ImageField
類只適用於 MultiPartParser
或 FileUploadParser
。大多數解析器,例如,JSON 不支持文件上傳。Django 的常規 FILE_UPLOAD_HANDLERS
用於處理上傳的文件。
FileField
文件表示。執行 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
設置鍵的值,除非另有設置,否則為True
。
ImageField
圖像表示。驗證上傳的文件內容是否匹配已知的圖像格式。
對應於 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
設置鍵的值,除非另有設置,否則為True
。
需要 Pillow
包或 PIL
包。建議使用 Pillow
包,因為不再主動維護 PIL
。
復合字段 (Composite fields)
ListField
驗證對象列表的字段類。
簽名: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
中的鍵始終假定為字符串值。
簽名:DictField(child=<A_FIELD_INSTANCE>)
child
—— 用於驗證字典中的值的字段實例。如果未提供此參數,則映射中的值將不會被驗證。
例如,要創建一個驗證字符串到字符串映射的字段,可以這樣寫:
document = DictField(child=CharField())
您也可以使用聲明式樣式,與 ListField
一樣。例如:
class DocumentField(DictField): child = CharField()
HStoreField
與 Django 的 postgres HStoreField
兼容的預配置的 DictField
。
簽名:HStoreField(child=<A_FIELD_INSTANCE>)
child
—— 用於驗證字典中的值的字段實例。默認子字段接受空字符串和空值。
請注意,子字段必須是 CharField
的實例,因為 hstore 擴展將值存儲為字符串。
JSONField
驗證傳入數據結構由有效 JSON 基元組成的字段類。在它的交替二進制模式中,它將表示和驗證 JSON 編碼的二進制字符串。
簽名:JSONField(binary)
binary
—— 如果設置為True
,那么該字段將輸出並驗證 JSON 編碼的字符串,而不是原始數據結構。默認是False
。
各種各樣的字段 (Miscellaneous fields)
ReadOnlyField
只返回字段的值而不進行修改的字段類。
當包含與屬性相關的字段名稱而不是模型字段時,默認情況下,此字段與 ModelSerializer
一起使用。
簽名:ReadOnlyField()
例如,如果 has_expired
是 Account
模型上的屬性,則以下序列化器會自動將其生成為 ReadOnlyField
:
class AccountSerializer(serializers.ModelSerializer): class Meta: model = Account fields = ('id', 'account_name', 'has_expired')
HiddenField
不根據用戶輸入獲取值,而是從默認值或可調用值中獲取值的字段類。
簽名:HiddenField()
例如,要包含始終提供當前時間作為序列化器驗證數據的一部分的字段,您將使用以下內容:
modified = serializers.HiddenField(default=timezone.now)
如果需要運行某些基於預先提供的字段值的驗證,通常只需要 HiddenField
類,而不是將所有這些字段公開給最終用戶。
有關 HiddenField
的更多示例,請參閱驗證器文檔。
ModelField
可以綁定到任意模型字段的通用字段。ModelField
類將序列化/反序列化的任務委托給其關聯的模型字段。該字段可用於為自定義模型字段創建序列化器字段,而無需創建新的自定義序列化器字段。
ModelSerializer
使用此字段來對應自定義模型字段類。
簽名:ModelField(model_field=<Django ModelField instance>)
ModelField
類通常供內部使用,但如果需要,可以由 API 使用。為了正確實例化 ModelField
,必須傳遞一個附屬於實例化模型的字段。例如:ModelField(model_field=MyModel()._meta.get_field('custom_field'))
SerializerMethodField
這是一個只讀字段。它通過調用附屬於序列化器類上的方法來獲取其值。它可用於將任何類型的數據添加到對象的序列化表示中。
簽名: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
自定義字段 (Custom fields)
如果想要創建自定義字段,則需要子類化 Field
,並重寫 .to_representation()
和 .to_internal_value()
方法中的一個或兩個。這兩種方法用於在初始數據類型和原始可序列化數據類型之間進行轉換。原始數據類型通常是數字,字符串,布爾值,date
/time
/datetime
或 None
。它們也可以是任何僅包含其他原始對象的列表或字典。可能支持其他類型,具體取決於您使用的渲染器。
調用 .to_representation()
方法將初始數據類型轉換為原始的可序列化數據類型。
調用 to_internal_value()
方法將原始數據類型恢復為其內部 python 表示。如果數據無效,此方法應該引發 serializers.ValidationError
異常。
請注意,2.x 版本中存在的 WritableField
類不再存在。 如果字段支持數據輸入,則應該子類化 Field
並重寫 to_internal_value()
。
舉個栗子
基本自定義字段 (A Basic Custom Field)
讓我們來看一個序列化一個表示 RGB 顏色值的類的例子:
class Color(object): """ 在 RGB 顏色空間中表示的顏色。 """ 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): """ 顏色對象被序列化為 'rgb(#, #, #)' 表示法。 """ 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__
拋出驗證錯誤 (Raising validation errors)
我們上面的 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', 'testing'), ('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']
在這里,目標和源屬性對(x
和 x_coordinate
,y
和 y_coordinate
)之間的映射在 IntegerField
聲明中處理。這是使用了 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.']})])
由於這個原因,嵌套的序列化器方法將是第一個嘗試。當嵌套的序列化器變得不可行或過於復雜時,您將使用自定義字段方法。
第三方包 (Third party packages)
以下是可用的第三方包。
DRF Compound Fields
drf-compound-fields 包提供“復合”序列化器字段,例如簡單值列表,它可以由其他字段描述,而不是使用 many = True
選項的序列化器。還提供了類型化字典和值的字段,它們可以是特定類型或該類型的項列表。
DRF Extra Fields
drf-extra-fields 包為 REST framework 提供了額外的序列化器字段,包括 Base64ImageField
和 PointField
類。
djangorestframework-recursive
djangorestframework-recursive 包為序列化和反序列化遞歸結構提供了 RecursiveField
。
django-rest-framework-gis
django-rest-framework-gis 包為 django rest framework 提供了地理插件,如 GeometryField
字段和 GeoJSON 序列化器。
django-rest-framework-hstore
django-rest-framework-hstore 包提供了 HStoreField
來支持 django-hstore DictionaryField
模型字段。