【超便利】Django FormMixinのsuccess_urlでフォーム送信後の画面遷移をスマートに制御


django.views.generic.edit.FormMixin.success_url は、Django のジェネリックビューにおいて、フォーム処理が成功した場合にリダイレクトするURLを指定するための属性です。この属性を設定することで、フォーム送信後にユーザーを自動的に別のページへ遷移させることができます。

具体的な動作

  1. ユーザーがフォームを送信し、フォーム検証が成功すると、form_valid() メソッドが呼び出されます。
  2. このメソッド内で、success_url 属性に設定されたURLへリダイレクトされます。
  3. デフォルトでは、success_url 属性は設定されていません。その場合、モデルオブジェクトの get_absolute_url() メソッドを使用してURLを取得しようとします。
  4. get_absolute_url() メソッドが定義されていない場合、ImproperlyConfigured 例外が発生します。

設定方法

success_url 属性は、ジェネリックビュークラス内で直接設定できます。以下は、例です。

from django.views.generic.edit import FormView

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm
    success_url = "/thanks/"

この例では、フォーム処理が成功した場合、/thanks/ URLへリダイレクトされます。

  • リダイレクト処理をカスタマイズしたい場合は、form_valid() メソッドをオーバーライドできます。
  • success_url 属性は、URL文字列だけでなく、URL逆引き関数も設定できます。


from django.views.generic.edit import FormView
from .forms import MyForm

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm
    success_url = "/thanks/"

例2:URL逆引き関数を使用したリダイレクト

この例では、URL逆引き関数を使用して、動的にリダイレクト先URLを決定するビューを定義します。

from django.shortcuts import reverse
from django.views.generic.edit import FormView
from .forms import MyForm

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm

    def form_valid(self, form):
        # リダイレクト先URLを動的に生成
        redirect_url = reverse('my_app:detail', kwargs={'pk': form.instance.pk})
        return super().form_valid(form)

例3:form_valid() メソッドをオーバーライドしてリダイレクト処理をカスタマイズ

この例では、form_valid() メソッドをオーバーライドして、リダイレクト処理をカスタマイズするビューを定義します。

from django.shortcuts import redirect
from django.views.generic.edit import FormView
from .forms import MyForm

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm

    def form_valid(self, form):
        # 成功メッセージを設定
        self.request.session['success_message'] = "フォーム送信が完了しました。"

        # 特定の条件に基づいてリダイレクト先URLを決定
        if form.instance.is_active:
            redirect_url = reverse('my_app:detail', kwargs={'pk': form.instance.pk})
        else:
            redirect_url = reverse('my_app:list')

        return redirect(redirect_url)
  • これらの例はあくまで基本的なものです。実際の開発においては、状況に応じて様々なカスタマイズを行うことができます。


Django の django.views.generic.edit.FormMixin.success_url 属性は、フォーム処理が成功した場合にリダイレクトするURLを指定するための便利な機能ですが、状況によっては別の方法でリダイレクト処理を行いたい場合があります。

そこで、ここでは success_url 属性を使用しない代替方法として、以下の3つの方法をご紹介します。

form_valid() メソッドをオーバーライドする

最も柔軟性の高い方法は、form_valid() メソッドをオーバーライドして、リダイレクト処理を独自に実装することです。この方法では、フォーム送信後の処理を完全に制御できます。

from django.shortcuts import redirect
from django.views.generic.edit import FormView
from .forms import MyForm

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm

    def form_valid(self, form):
        # 成功メッセージを設定
        self.request.session['success_message'] = "フォーム送信が完了しました。"

        # 特定の条件に基づいてリダイレクト先URLを決定
        if form.instance.is_active:
            redirect_url = reverse('my_app:detail', kwargs={'pk': form.instance.pk})
        else:
            redirect_url = reverse('my_app:list')

        return redirect(redirect_url)

シグナルを使用する

フォーム処理が成功した際にシグナルを発信し、それをリスナーで受け取ってリダイレクト処理を行う方法です。この方法では、form_valid() メソッドをオーバーライドする必要がなく、コードをより分割することができます。

from django.dispatch import Signal
from django.shortcuts import redirect
from django.views.generic.edit import FormView
from .forms import MyForm

form_submitted = Signal(providing_args=['form'])

class MyFormView(FormView):
    template_name = "my_form.html"
    form_class = MyForm

    def form_valid(self, form):
        form_submitted.send(sender=self, form=form)
        return super().form_valid(form)

def form_submitted_handler(sender, form, **kwargs):
    # リダイレクト処理
    redirect_url = reverse('my_app:detail', kwargs={'pk': form.instance.pk})
    return redirect(redirect_url)

form_submitted.connect(form_submitted_handler)

テンプレート内でリダイレクト処理を行う

JavaScript を使用して、テンプレート内でリダイレクト処理を行う方法です。この方法は、シンプルな場合にのみ適しています。

{% if form.is_valid %}
    <script>
        window.location.href = "{% url 'my_app:detail' pk=form.instance.pk %}";
    </script>
{% endif %}
方法利点欠点備考
form_valid() メソッドをオーバーライドする最も柔軟性が高いコードが複雑になる可能性がある
シグナルを使用するコードを分割できるシグナルの仕組みを理解する必要がある
テンプレート内でリダイレクト処理を行うシンプルJavaScript が必要複雑な処理には向かない