1

私の完璧主義のやり方では、あまり文書化されていないクラスベースのビューについてさらに質問するためにここにいます。

クラスベースのビューについて学習し、コードに潜んでいるのに 5 時間ほど費やしたところ、質問がありました。

私がやろうとしていることはばかげているのかもしれません。

簡単な例を挙げます:

class SearchFormView(FormView):
    template_name = 'search/search.html'
    form_class = SearchForm

    def get(self, request, *args, **kwargs):
        form = SearchForm(self.request.GET or None)
        if form.is_valid():
            self.mystuff = Stuff.objects.filter(title__icontains=form.cleaned_data['query'])[:10]

        return super(SearchFormView, self).get(request, *args, **kwargs)

これは完全に有効なクラスです (そうですよね?)。

フォームがあり、クエリ パラメーターを使用して GET 要求を行います。

魅力のように機能します。

しかし、想像してみてください... ある種の攻撃を防ぐためにクエリ入力を検証すると、クエリが悪意があることがわかったので、検証エラーを入力しました。

古い関数では、フォーム インスタンス (空) があり、必要に応じてデータと検証エラーを入れます。空の場合 (最初のリクエスト)、またはエラーでいっぱいの場合 (悪意のあるクエリの場合) は、常にそのインスタンスを返します。

問題は、クラスベースのビューにあります。私の get メソッドでは、SearchFormの追加のインスタンスを使用するので、検証用のものを配置するとそこにあり、親でgetを呼び出すと、空になる「form_class」のインスタンスが使用されます

したがって、常に同じフォームを使用する方法が必要だと思います。つまり、request メソッドを呼び出し、form_class (新しいフォームを作成しない) を選択し、データを渡し、検証すると、父親がそれを返します。検証のものを含むフォーム。

これを正しく説明したかどうかはわかりません。要するに、私は get でフォームのコピーを作成していますが、空になる別のコピーを持つ親の get を返すので、テンプレートを表示すると、送信されたフォームが空であるためエラーは発生しません。

何か案は?ありがとう。

4

2 に答える 2

3

あなたの問題はsuper(SearchFormView, self).get(request, *args, **kwargs)、独自のフォームと独自のコンテキストをレンダリングすることです。これは 3 行のビュー関数にすぎないため、その動作を変更するために必要なものを実際にオーバーライドする必要があります。

   def get(self, request, *args, **kwargs):
        form = SearchForm(self.request.GET or None)
        if form.is_valid():
            self.mystuff = Stuff.objects.filter(title__icontains=form.cleaned_data['query'])[:10]

        return self.render_to_response(self.get_context_data(form=form))

更新: スーパー コールを引き続き使用する場合の別のアイデア

def get(self, request, *args, **kwargs):
     self.form = SearchForm(self.request.GET or None)
     if self.form.is_valid():
         self.mystuff = Stuff.objects.filter(title__icontains=form.cleaned_data['query'])[:10]

     return super(SearchFormView, self).get(request, *args, **kwargs)


def get_form(self, form_class):
    """
    Returns an instance of the form to be used in this view.
    """
    return getattr(self, 'form', None) or form_class(**self.get_form_kwargs())
于 2012-01-18T18:58:46.943 に答える
0

問題は、HTTPメソッドがPOSTまたはPUTの場合にのみ、Djangoクラスベースのビューがフォームkwargsに入力されるという事実にあるようです。

class FormMixin(object):

    def get_form_kwargs(self):
        """
        Returns the keyword arguments for instanciating the form.
        """
        kwargs = {'initial': self.get_initial()}
        if self.request.method in ('POST', 'PUT'):
            kwargs.update({
                'data': self.request.POST,
                'files': self.request.FILES,
            })
        return kwargs

GETリクエストでフォーム(「検索」フォームなど)を使用したことがあるため、これも少し変わっていることがわかりました。これには、基本的な検証を実行する必要がありました。このようなビューでget_form_kwargs()メソッドをオーバーライドするだけで、HTTPメソッドがGETの場合でも、kwargs['data']アイテムにデータを入力できます。

于 2012-03-15T19:16:56.143 に答える