投稿/コメントを表示します。

お世話になります。
forms.Formクラスを継承したフォームクラスをクラスベースドビューで呼び出す時のことについて確認したいことがあります。
お手数をおかけしますが、どうぞよろしくお願いいたします。

forms.Formクラスを継承したフォームクラスを、generic.FormViewクラスまたはgeneric.Viewクラスを継承したビューで取得し、かつモデルフィールドの内容を変更(更新)することができました。
 POST実行時の処理
 1.cleanded_dataの辞書型データを受取とる
 2.モデルフィールドのオブジェクトをinstanceという変数に格納。
 3.モデルフィールドの属性をcleaned_dataの値で適宜セットして、instance.save()でオーバーライド
 4.return super().form_valid(form)すると、モデルフィールドの上書きができた。

しかし,forms.Formクラスをgeneric.Updateviewを継承したビューで取得しようとすると、BaseForm.__init__() got an unexpected keyword argument 'instance'
BaseForm.__init__() が予期せぬキーワード引数 'instance' を受け取りましたとエラーが返ります。
TypeError at /edit/105/
BaseForm.__init__() got an unexpected keyword argument 'instance'
Request Method:	GET
Request URL:	http://127.0.0.1:8000/edit/105/
Django Version:	4.1.3
Exception Type:	TypeError
Exception Value:	
BaseForm.__init__() got an unexpected keyword argument 'instance'
Exception Location:	C:\Users\arupa\Documents\django\pictures_app\venv\lib\site-packages\django\views\generic\edit.py, line 39, in get_form

私のコードの問題なのか、UpdateViewとforms.Formクラスを継承したフォームクラスの組み合わせはもともと出来ないのか。generic.UpdateViewとgeneric.FormViewの違いをedit.pyのコードをみて自分なりに考えたのですが、理解の誤りがあるか確認したいと思いました。
次回のゼミの時にでもご教示いただけるとありがたいです。

※結論としては、以下の2パターンで使い分けるのかと思います。

・モデルフィールドに関連しない処理のフォームの場合
forms.Formクラスを継承したフォームクラスを使用する。
クラスベースドビューで呼び出す場合は、generic.FormViewやgeneric.Veiw、テンプレートファイルを使ったページの表示の場合は、generic.TemplateVeiwを使う。

・モデルフィールドに反映するフォームを作成する場合
forms.ModelFormクラスを継承したフォームクラスを使う。forms.ModelFormはclass Meta内のmodelやフォームフィールドを自動で作成してくれる。
クラスベースドビューは、用途に合わせて、generic.UpdateView,DeleteView,CreateViewを使用する。

※generic.FormViewクラスが継承するclass FormMixin(ContextMixin):の処理のコードを参照しました。
get_formメソッドと戻り値を返すget_form_kwargsメソッド
POSTメソッドの場合は、form=sef.get_form_class()としてフォームクラスのインスタンスを取得して、キーワード引数にdata=request.POST、ファイルの時は、FILESを渡すと理解しました。

FormViewが継承するFormMixinクラス edit.py
class FormMixin(ContextMixin):

    def get_form(self, form_class=None):
        """Return an instance of the form to be used in this view."""
        if form_class is None:
            form_class = self.get_form_class()
        return form_class(**self.get_form_kwargs())

    def get_form_kwargs(self):
        """Return the keyword arguments for instantiating the form."""
        kwargs = {
            "initial": self.get_initial(),
            "prefix": self.get_prefix(),
        }

        if self.request.method in ("POST", "PUT"):
            kwargs.update(
                {
                    "data": self.request.POST,
                    "files": self.request.FILES,
                }
            )
        return kwargs

※generic.UpdateViewの場合
POST時に、BaseUpdateViewクラスのget_objectメソッドでモデルインスタンスをself.objectに格納するようです。

UpdateViewが継承するBaseUpdateView edit.py
class BaseUpdateView(ModelFormMixin, ProcessFormView):

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super().post(request, *args, **kwargs)

そして、私がform.Formクラスと関連づけたため、formViewクラスが継承するclass FormMixinクラスのget_form_kwargsメソッドが呼び出された。
メソッドを上書きしようとしたが、引数は以下の通り"data": self.request.POST,ファイルがある場合は、"files": self.request.FILES。
self.objectのモデルインスタンスを受取ってしまうと、予期せぬキーワード引数を受取りました、というエラーがかえってきたのか?と思いました。

formViewクラスが継承するclass FormMixinクラスのget_form_kwargs関数は、POSTメソッドの返り値を引数に取って、get_form関数に返す。
ここでエラーになった。

edit.py 39行目 エラーが発生した箇所です。
    def get_form(self, form_class=None):
        """Return an instance of the form to be used in this view."""
        if form_class is None:
            form_class = self.get_form_class()
        return form_class(**self.get_form_kwargs())

    def get_form_kwargs(self):
        """Return the keyword arguments for instantiating the form."""
        kwargs = {
            "initial": self.get_initial(),
            "prefix": self.get_prefix(),
        }

        if self.request.method in ("POST", "PUT"):
            kwargs.update(
                {
                    "data": self.request.POST,
                    "files": self.request.FILES,
                }
            )
        return kwargs

※UpdateViewが継承しているModelFormMixinのget_form_kwargsメソッド
属性がobjectの場合は "instance":self.objectの辞書をkwargsに代入するようになってます。
それゆえ、form.ModelFormクラスの場合はself.objectを引数にとれるし、モデルフィールドに反映する処理ができるのかと思いました。
class ModelFormMixin(FormMixin, SingleObjectMixin):

    def get_form_kwargs(self):
        """Return the keyword arguments for instantiating the form."""
        kwargs = super().get_form_kwargs()
        if hasattr(self, "object"):
            kwargs.update({"instance": self.object})
        return kwargs
	

理解不足のままの質問となり申し訳ございません。
次回のゼミの時にでも解説いただけるとありがたいです。

どうぞよろしくお願いいたします。
2023/02/21 19:46