[Django] カスタムバリデーター(CustomValidator)を作成する

DjangoでフォームやDBのフィールドに入力制限を設けたい場合に利用するバリデーター(Validator)を自作する方法のメモ

はじめに

Djangoには標準でvalidate_email MinLengthValidatorRegexValidatorなどのバリデーション関数やクラスが用意されています。

しかし作るアプリケーションによってはこれらのバリデーターだけでは足りない事も多々あります。  なのでここでは、バリデーターを自作する方法をさくっと紹介します。

RegexValidator

お手軽にバリデーターをカスタマイズするならRegexValidatorを利用する方法がおすすめです。

RegexValidatorは正規表現にマッチしない文字列が入力された時にValidationErrorを送出します。 つまり正規表現にマッチしない文字列は弾きます。

使い方は大きく2通りで、インスタンス化する時に正規表現文字列を渡す方法とサブクラスを作成する方法です。

インスタンス化する時に正規表現文字列を渡す

validate_ascii = RegexValidator(regex="^[a-zA-Z0-9]+$", message="エラーメッセージ")

引数に正規表現とエラーメッセージを渡して作る例です。

サブクラスを作成する

class CustomValidator(RegexValidator):
    regex = "^[a-zA-Z0-9]+$" # 正規表現
    message = "エラーメッセージ"
    inverse_match = False
    
validate_custom = CustomValidator()

クラス変数inverse_matchTrueにしておくと正規表現にマッチする場合にValidationErrorを送出するようになります。
ちょっと便利ですね。

同じバリデーターをいろんな場所で使いまわす場合はサブクラスを作っておいたほうが便利かもしれないですね。

カスタムバリデーター

RegexValidatorだけでは、実現できないバリデーションをする場合、受け入れたくない値が来た時にValidationError例外を送出する関数を定義する事で対応できます。

今回は関数を定義する方法で紹介しますが、実際にはバリデータークラスを作っておくほうが都合がいいと思います。(部分的に処理を変えたいときなどに便利なので)

次の例は、入力の中に最低でも1文字以上の数字(0~9)が入っているかを検証しています。

from django.core.exceptions import ValidationError

def validate_contain_number(value):
    for i in "0123456789":
            if i in value:
                return
    raise ValidationError("最低でも1文字は数字を入力してください。")

実際に使う

あとは、これらのバリデーターを利用するだけです。

class MyModel(model.Model):
    text = models.TextField(validators=[validate_contain_number])

バリデーションを行いたいフィールドの引数 validatorsにlistでバリデーション関数を渡してあげる事で利用できます。
listに複数のバリデーション関数をセットする事で、複数のバリデーションを実行させる事もできます。

まとめ

  • お手軽にバリデーションするならRegexValidatorを使う
  • 凝ったことがやりたければ、ValidationError例外を送出する関数を作る
参考

https://github.com/django/django/blob/505fec6badba0622bbf97bb659188c3d62a9bc58/django/core/validators.py