😭

[Django]プレビューのためにFormPreviewを使って欲しくない理由

2021/12/22に公開

はじめに

これは Django Advent Calendar 2021 13日目の記事です(空いていたので飛び入りで)。

Djangoでプレビューを実装したい、そういうときに django-formtools のFormPreviewを紹介しているケースがあります。しかし自分はこれを使って欲しくないと強く主張したいです。なぜ使って欲しくないかを記載します。

FormPreviewを使うべきでない理由

その理由は、FormPreviewがクラスベースビューを使用していないからです。

FormPreviewは自前で実装されたクラスで、Viewクラスを継承していません。Viewクラスを継承すると使えるメソッド、例えば setup() メソッドが使えません。初期化の方法も異なります。すごく戸惑いました。「フォームを引数として渡すの?」と。コードを読み解くのに時間がかかりました。

path('post/', SomeModelFormPreview(SomeModelForm)),

Djangoではクラスベースビューを使うのが普通ですが、そこにFormPreviewが入ると、別のやり方を覚える必要があります。

そして、プレビュー程度なら簡単に実装できます。パラメータを1つ追加して、 1 ならプレビュー、 2 なら実行で十分です(そのパラメータが 1 でも 2 でもない場合の考慮は必要ですが)。よく使うならFormViewを継承して、自前でプレビュークラスを作ってもいいでしょう。

プレビュー機能を実装するメリットに比べて、クラスベースビューとは異なる独自のビューを定義するデメリットの方が大きいと判断します。なので自分としては使って欲しくありません。

ちなみに、 django-formtools で提供されている WizardView については TemplateView を継承しているようです。こちらは使ったことありませんし、使用することを推奨するものではありませんが、少なくともFormPreviewとは状況は違い、クラスベースビューの枠組みで実装されているので、検討する価値はあると思います。

FormPreviewはなぜクラスベースビューでないのか

FormPreviewは元々 django.contrib.formtools.preview.FormPreview として、Djangoの一部でした。しかし、Django 1.8から削除されています。

https://docs.djangoproject.com/en/3.2/releases/1.8/#removal-of-django-contrib-formtools

その経緯はこちらに書かれています。Djangoの昔のことは分かりませんが、元々FormPreviewがあって、それからクラスベースビューができた結果、FormPreviewがクラスベースビューと合わなくなったのだと思われます。

https://code.djangoproject.com/ticket/23677

https://groups.google.com/g/django-developers/c/cJyL87v3BWw?pli=1

おわりに

自分はFormPreviewを使うことを推奨しませんが、それは、FormPreviewの品質に問題があるのではありません。Djangoが発展していった結果として、FormPreviewが古くなっただけにすぎません。

そして、 django プレビュー で検索すると、FormPreviewを推奨している記事が見つかります。もちろん、それらの記事が悪いわけではありません。ただ、記事の内容が古くなっただけです。

ただ、自分がFormPreviewで苦労しているのは事実です。そして、少なくとも新規コードでは使うべきでないと考えています。そこでこの記事を書きました。新規にプレビューを実装したい人がこの記事に目を留めてもらえれば幸いです。

Discussion