質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

2368閲覧

クラスベース汎用ビュー(FormView)内でフォームクラスに括弧をつけて初期値を指定すると"not callable"エラーになる

k-zil

総合スコア16

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2019/04/18 02:30

編集2019/04/18 02:35

前提・実現したいこと

pythonのフレームワークDjangoでシステムを構築中です。
form.pyのFormクラスで定義したフォームの初期値をビューから指定したいと思い、以下のページなどを参考にして、ビューのコードを書き換えたのですが、'EntryForm' object is not callableというエラーでDjangoに怒られてしまいます。
0. https://qiita.com/sapuri/items/f6fb992334b6afb6196e

  1. http://i2bskn.hateblo.jp/entry/20120826/1345936779

上記のページと自分のコードの差は、ビューが関数で書かれているかクラス(クラスベース汎用ビューFormView)で書かれているかという点だろうと推測していろいろ調べた結果、最終的には、ビュー内でget_initialメソッドをオーバーライドすることで初期値を指定することに成功はしたのですが、上記の参考ページのように、ビュー内でフォームクラス(クラス名EntryForm)に括弧をつけて値を指定する方法だと、なぜnot callableになるのかが分かりません。

'クラス'、'メソッド'、'関数'の基礎的知識が不足しているためだと思いますが、この戸惑いについて腹に落ちる解説、または参考ペーシを教えていただけますと幸いです。
あやふやな理解のまま開発を進めると、また同じような躓きで時間を取られそうで怖いので、一度きちんと理解したく、その手立てをご指南いただけると助かります。
どうかよろしくお願い致します。

該当のソースコード

python

1#forms.py 2class EntryForm(forms.Form): 3 name = forms.CharField( 4 max_length = 200, 5 initial = u'鈴木太郎', # 初期値 6 )

python

1#views.py 2#変更前のビュー 3class EntryInput(FormView): 4 form_class = EntryForm 5 template_name = "entry_input.html"

これを以下のように変更しました。(EntryFormに括弧をつけて初期値を指定。)

python

1#views.py 2#変更後のビュー(1) 3class EntryInput(FormView): 4 form_class = EntryForm( initial = {'name': u'佐藤次郎'} ) 5 template_name = "entry_input.html"

すると'EntryForm' object is not callableのエラーになります。

なお、以下のようのようにEntryFormの後ろに括弧を付けただけでも同じエラーになります。

python

1#views.py 2#変更後のビュー(2) 3class EntryInput(FormView): 4 form_class = EntryForm() 5 template_name = "entry_input.html"

いろいろ調べて、最終的には、

python

1#views.py 2#変更後のビュー(3) 3class EntryInput(FormView): 4 form_class = EntryForm 5 template_name = "entry_input.html" 6 7 def get_initial(self): 8 initial = super().get_initial() 9 initial["name"] = u'佐藤次郎' 10 return initial

とすることで初期値を変更できました。

※最終的に参考にさせてもらったサイトは以下です。
0. https://qiita.com/maisuto/items/33dfeb58f5953d1c5fdf#クラスベース汎用viewとの連携

  1. https://canon1ky.hatenablog.com/entry/2018/11/17/131128

知りたいこと

知りたいことは、なぜ変更後のビュー(1)や(2)では'EntryForm' object is not callableのエラーになってしまうのか、です。どうかご指南をよろしくお願い致します。

補足情報(FW/ツールのバージョンなど)

サーバ:さくらVPS(centOS 7.5)
Python:3.6.5
Django :2.1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

EntryFormはクラスオブジェクト、EntryForm()EntryFormクラスのインスタンスです。クラスをcallするとインスタンス化されるという仕組みです。

後ろの処理でform_classがクラスオブジェクトであることを期待してcallしている部分があったとします(フレームワークの内部かもしれませんが)。form_classにインスタンスを代入してしまうと、インスタンスに対するcallを試みて、'EntryForm' object is not callableになります。
(一般的なインスタンスは呼び出すことができません。特殊メソッド__call__を実装すればその限りではないが、こういうケースで使うものではない。念の為)

投稿2019/04/18 03:54

hayataka2049

総合スコア30933

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

k-zil

2019/04/23 07:04 編集

hayataka2049様 ご回答ありがとうございました。返信コメントでは文章がうまく装飾できなかったので回答の追加という形で返信させていただきました。お手数ですがどうぞよろしくお願い致します。
guest

0

hayataka2049様
ご回答ありがとうございました。せっかくヒントをいただいておきながら心苦しいのですが、今ひとつ理解できません。
すみません。質問の仕方を変えてみます。

元々viewを以下のようにしていました。

python

1#views.py 2#クラスベースビュー 3class EntryInput(FormView): 4 form_class = EntryForm( initial = {'name': u'佐藤次郎'} ) 5 template_name = "entry_input.html"

これだと元々に質問のとおり、'EntryForm' object is not callableのエラーになります。(EntryFormの後ろの括弧をなくせばエラーはなくなります)

次にこれを以下のように関数ベースビューにしてみました。

python

1#views.py 2#関数ベースビューに変更してみた(urls.py内の記述ももちろん少し修正した) 3def EntryInput(FormView): 4 form_class = EntryForm( initial = {'name': u'佐藤次郎'} ) 5 return render(request, 'entry_input.html', {'form': form_class} )

こうするとエラーは出ずに動作します。

前者のクラスベースビューの中でEntryFormに括弧をつけるとエラーになり、後者の関数ベースビューの中でEntryFormに括弧つけてもエラーにならない。この差は何なんでしょうか??
どのあたりの知識を習得すれば上記の疑問が解決できるのかご指南いただけますと助かります。
何卒よろしくお願い致します。

投稿2019/04/23 07:03

k-zil

総合スコア16

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/04/23 17:44

クラスベースビューだとform_classはクラス変数になり、その後の処理では、クラスが代入されていてインスタンスすることができる前提で扱われます。 関数ベースビューではform_classは関数のローカル変数であり、外部からは見えません。この名前である必要性もありません。変数を作らなくても構いません。 a = EntryForm( initial = {'name': u'佐藤次郎'} ) return render(request, 'entry_input.html', {'form': a} ) とか return render(request, 'entry_input.html', {'form': EntryForm( initial = {'name': u'佐藤次郎'} )} ) で動くということです。 見た目は少しだけ似ていますが、まったく別の仕組みで動いていると理解してください。
hayataka2049

2019/04/23 17:45 編集

より深く理解するためには、まずクラスや関数などのpythonの基本的な機能についてしっかり理解してください。その上で、エラーメッセージのtracebackを見て、どこでエラーになっているのかを確認する(django内部の動作までコードを追って把握していく)ことが理解の助けになると思います。
k-zil

2019/05/05 04:12

hayataka2049様 いただいた回答を何度も読み返し、いろいろと調べた結果、ようやく問題の本質が理解できました。 最初の回答でご指摘いただいたとおり、djangoの内部(django.views.generic.editのFormMixin)で、form_classをクラスオブジェクトであると期待してcallしている部分がありました。 djangoのエラーメッセージのTracebackでもその部分が問題の箇所としてちゃんと明示されておりました。 今回の失敗は、 ・form_classが特別な変数である(クラス継承元の中でクラスオブジェクトとして扱われる)ということに全く意識が行かなった ・Traceback等で指摘されたエラー内容をきちんと理解していなかった 今回のエラーになった際、EntryFormの後に括弧を付けてみた箇所がTracebackでは明示されないことを不思議に思っていました。 問題はそこではなく、hayataka2049様の仰るとおり、その後の処理におけるform_class変数の扱いに注意を向けるべきでした。 今思えば最初にいただいた回答のとおりでした。 大変勉強になりました。 今後は恐れずTracebackで指摘された箇所をdjango内部まで追って理解するようにしたいと思います。 ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問