Djangoのクラスベース汎用ビューで正常な場合のページ遷移先の指定方法として2種類あります。一つはクラス変数のsuccess_urlを使う方法です。もう一つはメソッドのget_success_url()を使う方法です。
この2つの使い分けはどうしたらよいのでしょうか。
さらに、URLの逆引きに使う関数としてreverse()とreverse_lazy()という似たようなものがあります。これらの違いも一緒に以下の例を使って説明してみたいと思います。
(省略)
from django.urls import reverse_lazy
class FormView(FormView):
success_url = reverse_lazy(‘app:index’)
上の例ではクラスベース汎用ビューの一つであるFormViewのクラス変数success_urlに対してreverse_lazy()を使っています。ここでもしreverse関数を使うとImproperlyConfiguredというエラーがDjangoから返ってきてしまいます。
URLの逆引きを今は出来ないよとDjangoが怒っている訳です。なぜなら、クラス変数を設定する段階ではまだURLConf(=urls.py)を読み込んでいないからです。
そこでreverse_lazy()というreverse()の遅延評価バージョンを使ってこの問題を解消します。遅延評価というのは、実際に処理(ここではURLの逆引き)をするのは後回しにするということです。
success_urlについてですが、これは静的ページ(URLが変わらない)にしか使えません。
(省略)
from django.urls import reverse
class UpdateView(UpdateView):
(省略)
def get_success_url(self):
return reverse(‘app:detail’, kwargs={‘pk’: self.kwargs[‘pk’]})
上の例ではクラスベース汎用ビューの一つであるUpdateViewのget_success_url()メソッドをオーバーライドしています。
クラス変数のsuccess_urlは静的ページにしか使えませんでしたが、get_success_url()メソッドではselfからURLに含まれる変数を取得できます。これを使ってURLがその都度変わる動的ページを遷移先として指定できます。
そして、get_success_url()メソッドが呼ばれる時点ではURLConfはすでにロード済みなのでreverse関数でもOKなのです。
最後に元も子もない事を言いますが、reverse関数ではなくreverse_lazy関数を使っていれば問題なく処理されてしまうのでした。。