DjangoにてFormsetを用いたフォームがis_valid()で必ずFalseになってしまうときの対処法

今回はDjangoの formset_factory における formset を用いてフォームを作成したときに Post したデータがバリデーションの際に必ず False になってしまう時の対処法を解説いたします。

私自身もこれについて、ちょっとのミスで半日以上費やしてしまったので他にこのような悲劇に見舞われる方が出ないように対処法を記していきたいと思います。。。

スポンサーリンク
目次

事象

まずは事象について詳しく状況を説明いたします。
対処法だけ知りたいという方はこちらまでスキップしてください。

事象は formset_factory で作成したフォームに適当な値を入れて、いざDBの操作をしようとしたときにその前のバリデーションチェック関数にあたる is_valid() で False となりはじかれてしまうといった事象です。

またこれが非常に厄介なことにバリデーションエラーになっている箇所を詳しく見ようとしても肝心の erros にはエラー情報は入っていないし「どこのフィールドでおかしくなっているかわからん!」というような状況だと思います。

バリデーションエラーになっていないのに何で is_valid() がエラーなんじゃい! is_valid() 外したろかっていう感じで躍起になっていることでしょうが一旦落ち着けばなんてことはない事象だということがわかります。

原因

先に結論を述べると原因は Post したデータの中に formset 管理用のパラメータが存在しないことにあります。

このエラーは formset.errors には乗らないのですが、 formset.non_form_errors の中に原因が記されています。

ManagementForm data is missing or has been tampered with. Missing fields: form-INITIAL_FORMS. You may need to file a bug report if the issue persists.

これを見てわかる通り、 “form-INITIAL_FORMS” がないと怒ってらっしゃいます。
この文を見て、わかる人はわかると思いますが formset 用の管理パラメータが template にないことがこのエラーを発生させております。

管理用のパラメータは tmplate ファイルに {{フォームセット名.management_form }} と書くことで用意できますが、要はそれを記載し忘れているということです。

対策

対策は簡単です。

原因の項目でもお話ししましたが以下のコードを template ファイルに記載してあげるだけです。

{{フォームセット名.management_form }}

記載する場所はどこでもいいとは思いますが、以下のように formset のすぐ下に書いてあげれば見返したときにわかりやすいかと思います。

これで恐らく is_valid 関数が突破できると思いますので、書き忘れている人は記載してあげてください。

いかがでしょうか。
この対策で治らないという人がいましたらコメントでご連絡いただければ幸いです。

また別途 formset の扱い方や動的に操作する方法は記事にしようと思いますので使い方がそもそもわからんという人はそちらをご参照ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

本業ではPHPを使ったWEBアプリやJavaを使用した基幹アプリを作成しております。Pythonは個人的に勉強しており、E資格を取ったりしたおかげで、業務でAIの研究とかも任されるようになりました。学習のアウトプットのために本サイトを運営しておりますが、これからPythonを学ぶという人のお役に立てればいいなと思います。わからないことや調査して記事にしてほしいことがございましたらご連絡いただけると幸いです。

コメント

コメントする

目次
閉じる