Django模型驗證器詳解和原始碼分析
阿新 • • 發佈:2020-09-07
### 轉發請註明來源
在Django的模型欄位引數中,有一個引數叫做`validators`,這個引數是用來指定當前欄位需要使用的驗證器,也就是對欄位資料的合法性進行驗證,比如大小、型別等。
Django的驗證器可以分為模型相關的驗證器和表單相關的驗證器,它們基本類似,但在使用上有區別。
**本文討論的是模型相關的驗證器。**
## 一、自定義驗證器
一個驗證器其實就是一個可呼叫的物件(函式或類),接收一個初始輸入值作為引數,對這個值進行一系列邏輯判斷,如果不滿足某些規則或者條件,則表示驗證不通過,丟擲一個`ValidationError`異常。如果滿足條件則通過驗證,不返回任何內容(也就是預設的return None),可以繼續下一步。
驗證器具有重要作用,可以被重用在別的欄位上,是工具型別的邏輯封裝。
下面是一個驗證器的例子,它只允許偶數通過驗證:
```python
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
def validate_even(value):
if value % 2 != 0:
raise ValidationError(
_('%(value)s is not an even number'),
params={'value': value},
)
```
通過下面的方式,將偶數驗證器應用在欄位上:
```python
from django.db import models
class MyModel(models.Model):
even_field = models.IntegerField(validators=[validate_even])
```
因為驗證器執行之前,(輸入的)資料會被轉換為 Python 物件,因此我們可以將同樣的驗證器用在 Django form 表單中(事實上Django為表單提供了另外一些驗證器):
```python
from django import forms
class MyForm(forms.Form):
even_field = forms.IntegerField(validators=[validate_even])
```
你還可以通過Python的魔法方法`__cal__()`編寫更復雜的可配置的驗證器,比如Django內建的`RegexValidator`驗證器就是這麼幹的。
驗證器也可以是一個類,但這時候就比較複雜了,需要確保它可以被遷移框架序列化,確保編寫了`deconstruction()`和`__eq__()`方法。*這種做法很難找到參考文獻和博文,要靠自己摸索或者研究DJango原始碼。*
## 二、工作機制
讓我們來測試一下上面寫的驗證器:
```python
>>> from .models import MyModel
>>> a = MyModel.objects.create(even_field=3)
>>