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”上的实例,该实例将为空。

所以,我认为应该有一种方法,我总是使用相同的表单,我的意思是:我调用请求方法,我选择 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

问题似乎是基于 Django 类的视图仅在 HTTP 方法为 POST 或 PUT 时才填充表单 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() 方法,以填充 kwargs['data'] 项,即使 HTTP 方法是 GET 也是如此。

于 2012-03-15T19:16:56.143 回答