英語613639 views
数学講師2886227 views
世界の国564520 views
高校物理160203 views
中学英語811710 views
中学社会668760 views
高校国語788336 views
高校化学2924392 views
LaTeX962153 views
Computer368106 views
Help
Tools
NewsSpreadsheetCalendarSlidesTier ListPen ToolIllustrationCrayonPixel ArtASCII ArtPerspectiveEndless StairsGraphMind MapER DiagramFamily TreeMemeCurved TextImage EditorMosaicRetro FilterPencil SketchOCR/HighlighterMakeup EditorFaviconVideo TrimmerScrolling VideoVideo TitleColor PickerColor ExtractorBonfireFireworksWater RippleWater SplashBreaking GlassWood GrainMarble TextureCSS ButtonIcon MakerBar ChartGrouped Bar ChartStacked Bar ChartPie ChartLine ChartArea ChartStacked Area ChartScatter Plot3D Bar Chart3D Pie ChartBar Chart RaceBubble ChartPopulation PyramidPictogramEarningsCandlestick ChartInvestment RiskMortgage SimulatorCalculatorMatrix CalculatorFunction GraphPolynomial ExpansionVenn DiagramField VisualizerRubik's Cube Group TheoryTraveling SalesmanVoronoi and DelaunayFractalColumn ArithmeticDraw Math FiguresArithmetic AnimationArithmetic Word ProblemsCounting with Tree DiagramsCube NetsCross SectionsMotion PathMechanicsWavesLight and LensesThermodynamicsHow Semiconductors WorkMolecular StructuresAtomic OrbitalsElectrochemical CellsChemical EquilibriumCrystal LatticesBuffer pHComplex IonsDNA Double HelixCell DivisionMembrane ChannelsNerve ImpulseRock ClassificationWeatherConstellationsSolar and Lunar Eclipses3D ModelingFloor PlanSeismic StructuresIntersection TurnMaglevCooking AnimationOrigamiLive Viewer CountGeoJSON MapRailway MapPopulation MapCrime MapLand Price MapSchool MapShrine and Castle MapHouse of Representatives MapWord MapSolitaireReversiHakoiri MusumeChessHamburgerRippleSlide Puzzle MakerNeon PinballNovel MakerJapanese Typing PracticePiano Score EditorMusic Theory

English

Django のバリデーションの仕組み(clean メソッドとバリデータ)

Django のフォームバリデーションは、is_valid() を呼び出したときに自動的に実行されます。フィールド型に組み込まれた基本検証だけでなく、バリデータの追加やクリーンメソッドの定義によって、独自の検証ロジックを柔軟に組み込めます。

バリデーションの実行順序

is_valid() を呼ぶと、内部では以下の順序でバリデーションが進みます。

各フィールドの to_python()(型変換)
各フィールドの validate()(フィールド固有の検証)
各フィールドの run_validators()(バリデータの実行)
各フィールドの clean_フィールド名()(フィールド単位のカスタム検証)
フォーム全体の clean()(複数フィールドにまたがる検証)

エラーが発生した段階で、そのフィールドのバリデーションは中断されます。ただし他のフィールドの検証は続行されるため、1 回の送信ですべてのエラーをまとめて表示できます。

バリデータ(validators)

バリデータは単一の値を受け取り、条件を満たさない場合に ValidationError を送出する関数またはクラスです。フィールド定義時に validators パラメータで指定します。

from django.core.validators import MinLengthValidator, RegexValidator

class SignupForm(forms.Form):
    username = forms.CharField(
        max_length=30,
        validators=[
            MinLengthValidator(3, message='3文字以上で入力してください'),
            RegexValidator(
                regex=r'^[a-zA-Z0-9_]+$',
                message='英数字とアンダースコアのみ使用できます'
            ),
        ]
    )

Django には便利な組み込みバリデータが用意されています。

バリデータ検証内容
MinLengthValidator最小文字数
MaxLengthValidator最大文字数
MinValueValidator最小値(数値)
バリデータ検証内容
MaxValueValidator最大値(数値)
RegexValidator正規表現パターン
URLValidatorURL 形式

独自のバリデータを関数として定義することも可能です。

from django.core.exceptions import ValidationError

def validate_no_profanity(value):
    forbidden = ['spam', 'abuse']
    for word in forbidden:
        if word in value.lower():
            raise ValidationError(
                f'「{word}」は使用できません。'
            )

class CommentForm(forms.Form):
    text = forms.CharField(
        widget=forms.Textarea,
        validators=[validate_no_profanity]
    )

バリデータは再利用しやすいため、複数のフォームで同じ検証ロジックを共有したいときに適しています。

clean_フィールド名(フィールド単位の検証)

特定のフィールドに対するカスタム検証は、clean_フィールド名 というメソッドで定義します。

class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        fields = ['title', 'body']

    def clean_title(self):
        title = self.cleaned_data['title']
        if Article.objects.filter(title=title).exists():
            raise ValidationError('同じタイトルの記事がすでに存在します。')
        return title

clean_titletitle フィールドの基本バリデーション(型チェック・max_length など)が完了した後に呼び出されます。self.cleaned_data['title'] には型変換済みの安全な値が入っており、この値に対してカスタム検証を行います。

検証を通過した場合は値を return で返す必要があります。返し忘れると cleaned_data から値が消えてしまうため注意してください。

validators

再利用可能な検証関数。複数のフォームで同じロジックを共有できる

clean_フィールド名

フォーム固有のカスタム検証。データベースへの問い合わせを伴う検証に向く

clean(フォーム全体の検証)

複数のフィールドにまたがるバリデーション——たとえば「パスワードと確認パスワードの一致」——は clean メソッドで行います。

class PasswordChangeForm(forms.Form):
    password = forms.CharField(widget=forms.PasswordInput, label='新しいパスワード')
    password_confirm = forms.CharField(widget=forms.PasswordInput, label='パスワード確認')

    def clean(self):
        cleaned_data = super().clean()
        password = cleaned_data.get('password')
        password_confirm = cleaned_data.get('password_confirm')

        if password and password_confirm and password != password_confirm:
            raise ValidationError('パスワードが一致しません。')

        return cleaned_data

clean メソッドの中では super().clean() を最初に呼び出し、各フィールドの検証結果を取得します。get で値を取り出しているのは、先行するフィールドバリデーションでエラーが発生した場合に cleaned_data にキーが存在しないことがあるためです。

clean メソッドで raise された ValidationError は、特定のフィールドではなくフォーム全体のエラー(non_field_errors)として扱われます。テンプレートでは次のように表示します。

{{ form.non_field_errors }}
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">変更</button>
</form>

特定フィールドにエラーを紐づける

clean メソッド内で、エラーを特定のフィールドに紐づけたい場合は add_error を使います。

def clean(self):
    cleaned_data = super().clean()
    start = cleaned_data.get('start_date')
    end = cleaned_data.get('end_date')

    if start and end and start > end:
        self.add_error('end_date', '終了日は開始日より後にしてください。')

    return cleaned_data

add_error を使うと、エラーメッセージがフォーム全体ではなく指定したフィールドに表示されるため、ユーザーにとってどこを直せばよいかが明確になります。

ModelForm でのバリデーション

ModelForm ではフォームのバリデーションに加えて、モデルの unique 制約や unique_together 制約も自動的に検証されます。

class Article(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(unique=True)

この Article モデルに対して ModelForm を使えば、タイトルやスラッグの重複チェックをフォーム側に手書きする必要はありません。

バリデーションの階層構造をまとめると、「フィールド型の基本検証 → バリデータ → clean_フィールド名 → clean」の順で段階的に検証が行われます。単純な入力チェックはバリデータや組み込みフィールドに任せ、ビジネスロジックを伴う検証はクリーンメソッドに書く——この役割分担がバリデーション設計の基本方針になります。