1. はじめに
前回、Pythonの復習も兼ねて基本的な入力チェックを自作の関数として実装しました。
前の案件ではDjangoを使ってWebアプリ開発に携わっていたのですが、当時は完成させることが優先で、フォームの入力チェックの仕組みをきちんと理解できていなかったように思います。
今回はPythonを学び直す中で改めてDjangoに触れる機会があったので、前回自作した入力チェックの関数を、Djangoではどのように実装できるのか整理してみました。
2. Djangoとは
Djangoは、Pythonで書かれたWebアプリケーションフレームワークです。
フォームの入力チェックやデータベース操作など、Webアプリケーション開発に必要な機能があらかじめ用意されており、自分でゼロから実装する手間を減らせるのが特徴です。
今回は、この中でも「フォームの入力チェック機能」に焦点を当てて紹介します。
3.Djangoで入力チェックを実装してみた
※以降の「実行結果」について、
form.errorsは実際にはHTML形式で出力されますが、この記事では内容が分かりやすいよう、エラーメッセージ部分だけを記載しています。
3-1.必須チェック
前回は、validate_required()という関数を自作し、値が入力されているかどうかをチェックしていました。
Djangoでは、この必須チェックがデフォルトで組み込まれています。
実装例
from django import forms
class UserForm(forms.Form):
username = forms.CharField()
Djangoのフォームフィールドは、特に指定しなければデフォルトで必須(required=True)として扱われます。
成功パターン(値が入力されている場合)
form = UserForm(data={"username": "taro"})
print(form.is_valid())
実行結果:
True
前回自作したvalidate_required()はNoneや空文字を条件分岐で判定していましたが、Djangoではフィールドを定義するだけで同様のチェックができます。
失敗パターン(値が空の場合)
form = UserForm(data={"username": ""})
print(form.is_valid())
print(form.errors)
実行結果:
False
このフィールドは必須です。
もし必須にしたくない項目がある場合は、required=Falseを指定します。
required=Falseを指定すると、値が空でもエラーにならず、入力チェックを通過します。
class UserForm(forms.Form):
username = forms.CharField(required=False)
form = UserForm(data={"username": ""})
print(form.is_valid())
実行結果:
True
3-2.文字数チェック
前回は、validate_length()という関数を自作し、入力値が指定した文字数の範囲内かどうかをチェックしていました。
Djangoでは、max_lengthとmin_lengthという引数に値を指定するだけで、同様のチェックができます。
実装例
from django import forms
class UserForm(forms.Form):
username = forms.CharField(min_length=3, max_length=10)
成功パターン(文字数が範囲内の場合)
form = UserForm(data={"username": "taro"})
print(form.is_valid())
実行結果:
True
失敗パターン(文字数が範囲外の場合)
form = UserForm(data={"username": "ta"})
print(form.is_valid())
print(form.errors)
実行結果:
False
この値が少なくとも 3 文字以上であることを確認してください (2 文字になっています)。
前回はlen()を使って自分で文字数を数え、範囲外の場合にFalseを返す処理を実装していましたが、Djangoではmin_lengthとmax_lengthを指定するだけで、同様のチェックを行ってくれます。
3-3.数値の型・範囲チェック
前回は、validate_range()という関数を自作し、入力された数値が指定した範囲内かどうかをチェックしていました。
Djangoでは、MinValueValidatorとMaxValueValidatorというバリデータを指定することで、同様のチェックができます。
実装例
from django import forms
from django.core.validators import MinValueValidator, MaxValueValidator
class ScoreForm(forms.Form):
score = forms.IntegerField(
validators=[MinValueValidator(0), MaxValueValidator(100)]
)
成功パターン(範囲内の数値の場合)
form = ScoreForm(data={"score": 80})
print(form.is_valid())
実行結果:
True
失敗パターン(範囲外の数値の場合)
form = ScoreForm(data={"score": 110})
print(form.is_valid())
print(form.errors)
実行結果:
False
この値は 100 以下でなければなりません。
前回はif value < min_valueのような比較を書いていましたが、DjangoではMinValueValidatorとMaxValueValidatorをvalidatorsに渡すだけで、同様のチェックができます。
forms.IntegerFieldを使うことで数値以外の入力も弾かれるため、今回は数値チェックを省略しています。
3-4.半角英数字チェック
前回は、validate_alphanumeric()という関数を自作し、re.fullmatch()を使って入力値が半角英数字のみで構成されているかをチェックしていました。
Djangoでは、RegexValidatorというバリデータを指定することで、同様のチェックができます。
実装例
from django import forms
from django.core.validators import RegexValidator
alphanumeric_validator = RegexValidator(
regex=r"^[a-zA-Z0-9]+$",
message="半角英数字で入力してください。"
)
class UserIdForm(forms.Form):
user_id = forms.CharField(validators=[alphanumeric_validator])
成功パターン(半角英数字のみの場合)
form = UserIdForm(data={"user_id": "user123"})
print(form.is_valid())
実行結果:
True
失敗パターン(半角英数字以外が含まれる場合)
form = UserIdForm(data={"user_id": "user_123"})
print(form.is_valid())
print(form.errors)
実行結果:
False
半角英数字で入力してください。
RegexValidatorにはエラーメッセージも指定できるため、前回のelse節に書いていたメッセージも、そのままmessage引数に移すことができます。
3-5.複合チェック
前回は、validate_user_id()という関数を作り、必須チェック・文字数チェック・半角英数字チェックを組み合わせて、ユーザーIDの入力ルールをまとめてチェックしていました。
Djangoでは、これまで紹介した各チェックをフィールドの定義にまとめて指定するだけで、複合チェックが実現できます。
実装例
from django import forms
from django.core.validators import RegexValidator
alphanumeric_validator = RegexValidator(
regex=r"^[a-zA-Z0-9]+$",
message="半角英数字で入力してください。"
)
class UserIdForm(forms.Form):
user_id = forms.CharField(
min_length=3,
max_length=10,
validators=[alphanumeric_validator]
)
このフィールド定義には、以下の3つのチェックがまとめて含まれています。
- 必須チェック(デフォルトで
required=True) - 文字数チェック(
min_length、max_length) - 半角英数字チェック(
RegexValidator)
成功パターン(すべての条件を満たす場合)
form = UserIdForm(data={"user_id": "user123"})
print(form.is_valid())
実行結果:
True
失敗パターン(複数条件に違反する場合)
form = UserIdForm(data={"user_id": "u@"})
print(form.is_valid())
print(form.errors)
実行結果:
False
半角英数字で入力してください。
この値が少なくとも 3 文字以上であることを確認してください (2 文字になっています)。
該当するすべてのエラーがまとめて返ってくるため、「どの項目で、何が原因で失敗したか」を一度に確認できます。
4.まとめ
今回は、前回自作した入力チェックの関数を、Djangoではどう実装できるか整理しました。
前回1つずつ関数として実装していたチェック処理が、Djangoではフィールドの定義やvalidatorsの指定だけで、簡単に実現できることが分かりました。
同時に、以前実務でDjangoを使っていたときは何となくで動かしていた仕組みも、今回自分で書いたコードと比較しながら整理することで、内部でどう判定されているのかをイメージできるようになりました。
今後は、ModelFormを使った実装や、clean()メソッドを使った独自バリデーションについても学んでいきたいと思います。