Djangoにおけるバリデーション設定の基本を説明します。
なおFormクラスおよびModelFormクラスを利用した基本的なフォーム画面作成の手順は本記事では説明しませんので、下記の関連ページをご覧下さい。またuserアプリケーションおよびnew.htmlテンプレートが作成済であることを前提としています。
関連ページ
バリデーションの設定概要
バリデーションの設定方法は大きく分けて以下のように分けられます。
・CharFieldなどの入力フィールドの属性(オプション)として設定する。
・clean_フィールド名()メソッド、clean()メソッドを利用する。
・独自の関数として用意する。
・django.core.validatorsモジュールのバリデーションを利用する。
以下FormクラスおよびModelFormクラスそれぞれのパターンに分けて具体的なコードで説明していきます。views.pyとnew.htmlテンプレートは共通のファイルで実行できます。
Formクラス
user/forms.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
from django import forms from django.core.exceptions import ValidationError # def check_age(value): # if value < 10 or value > 100: # raise ValidationError('10〜100歳が範囲ですよ!') class UserForm(forms.Form): name = forms.CharField(label='名前', required=False, max_length=100) nickname = forms.CharField(label='ニックネーム', required=False, min_length=3, max_length=10, error_messages={'required': '必須です!', 'min_length': '3文字以上です!' }) email = forms.EmailField(label='メール', max_length=100) age = forms.IntegerField(label='年齢') #age = forms.IntegerField(label='年齢', validators=[check_age]) def clean_age(self): age = self.cleaned_data.get('age') if age < 10 or age > 100: raise forms.ValidationError('10〜100歳のみです!') return age def clean(self): cleaned_data = super().clean() name = cleaned_data.get('name') nickname = cleaned_data.get('nickname') if not (name or nickname): raise forms.ValidationError("名前かニックネームのどちらかを入力して下さい") return cleaned_data |
11行目
requiredやmax_lengthは、入力フィールドの属性として設定するもっともシンプルなバリデーションです。フィールドはデフォルトではrequired=Trueが設定されており入力必須となっています。CharFieldやIntegerFieldなどの入力フィールドの種類によってバリデーションの属性の種類は若干変わってきます。各フィールドのバリデーションについては ビルトインの Field クラス をご参照下さい。また後述しますが、ModelFormではrequiredやmin_lengthなどは使えずdjango.core.validatorsモジュールのビルトインのバリデータ等を利用する必要があります。
21〜25行目
clean_フィールド名()メソッドで、そのフィールドに対してカスタマイズしたバリデーション処理を記述することができます。
27〜33行目
clean_フィールド名()メソッドは個別のフィールドごとの処理ですが、clean()メソッドでは複数のフィールドに対してバリデーションを設定することができます。このclean()によって出力されるエラーメッセージはテンプレートにおいて{{ form.as_p }}で出力させる場合、その中の要素の一番上に表示されます。
5〜7行目
独自のバリデーションの関数(上記ではcheck_ageという名前を付けた)を用意しています。上記ではclean_ageと同じ処理の関数を記述しています。ValidationErrorでバリデーションチェック時に意図的にエラーを出力するようにします。2行目においてValidationErrorをインポートしています。このバリデーションをフィールドに設定する場合は、19行目のコメントアウトした方を利用します。属性として、validators=[check_age]を設定しているのが確認できます。
ModelFormクラス
モデルからフォーム画面を作成しています。上述したFormクラスによる作成と用意しているフィールドの種類が違うことをご了承下さい。また様々なバリデーションによる設定を説明しているため若干統一性がないこともご了承下さい。
user/models.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
from django.db import models from django.core.validators import MinLengthValidator, RegexValidator from django.core.exceptions import ValidationError def check_age(value): if value < 10 or value > 100: raise ValidationError('10〜100歳が範囲ですよ!') class Member(models.Model): name = models.CharField(max_length=100) nickname = models.CharField(max_length=100, validators=[MinLengthValidator(5, '5文字以上です!'), RegexValidator(r'^[a-zA-Z0-9]*$', '英数字のみです!')]) age = models.IntegerField(default=0, validators=[check_age]) def __str__(self): return self.name |
12行目
フォームフィールド型(forms.〜)と違いモデルフィールド型(models.〜)は、その属性に設定するバリデーションの種類は少ないです。(それら種類についてはフィールドの型をご参照下さい)。仮にここでmin_lengthや入力必須でないようにするrequired=Falseを記述するとエラーとなります。もしrequired=Falseを設定したい場合は、forms.py側に設定して下さい(後述)。
14/15行目
django.core.validatorsモジュールで用意されているバリデータをvalidators=[]に設定しています。2行目でインポートしていることに注意して下さい(それら種類についてはビルトインのバリデータをご参照下さい)。第1引数では条件、第2引数ではエラーメッセージを設定しています。
16行目
独自のバリデーションの関数(check_age)も設定できます。
user/forms.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
from django import forms from .models import Member class UserForm(forms.ModelForm): #nameをrequired = Falseにする def __init__(self, *args, **kwd): super(UserForm, self).__init__(*args, **kwd) self.fields["name"].required = False class Meta: model = Member fields = ('name', 'nickname', 'age') labels = { 'name': '名前', 'nickname': 'ニックネーム', 'age': '年齢' } error_messages = { 'name': { 'required': '必須です!', 'max_length': '長いです' }, 'nickname': { 'required': '必須です!', 'max_length': '長いです', } } help_texts = { 'name': '名前を入力して下さい', 'age': '年齢です' } # def clean_age(self): # age = self.cleaned_data.get('age') # if age < 10 or age > 100: # raise forms.ValidationError('10〜100歳のみです!') # return age |
8〜10行目
nameフィールドを「required = False」に設定しています。これをmodels.py側のフィールドの属性に設定するとエラーとなります。
35〜39行目
コメントアウトしていますがclean_フィールド名()メソッド、もしくはclean()メソッドも利用できます。
views.pyとnew.htmlテンプレート
FormクラスおよびModelFormクラスによるフォーム画面の記述をしてきましたが、以下views.pyとnew.htmlテンプレートは共通のファイルで利用できます。
user/views.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from django.shortcuts import render from .forms import UserForm def new(request): params = {'message': '', 'form': None} if request.method == 'POST': form = UserForm(request.POST) params['form'] = form if form.is_valid(): params['message'] = 'OK' else: params['message'] = 'まだ登録できません' else: params['form'] = UserForm() return render(request, 'user/new.html', params) |
10行目
is_valid()でバリデーションのチェックをチェックをおこなっています。モデルからフォーム画面を作成した場合は、次の行にform.save()を記述するとデータベースにフォームに入力された値を保存できます。
user/templates/user/new.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>フォーム</title> </head> <body> <h1>メンバー登録フォーム</h1> <form method="POST" novalidate> {% csrf_token %} {{ form.as_p }} <button type="submit">送信</button> </form> <p>{{ message }}</p> </body> </html> |
参照ページ
django ドキュメント
django.core.validators のソースコード