验证 get 请求中的表单,如何?

发布于 2024-12-27 19:49:21 字数 1158 浏览 0 评论 0原文

以我的完美主义方式,我来这里是为了提出更多关于没有充分记录的基于阶级的观点的问题。

我花了大约 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 的额外实例,因此如果我放置验证内容,那么如果我在 father 上调用 get它将使用“form_class”上的空实例。

所以,我认为应该有一种方法让我始终使用相同的表单,我的意思是:我调用请求方法,我选择 form_class (而不是创建新表单),传递数据,验证,父亲将返回该数据带有验证内容的表单。

我不确定我的解释是否正确。简而言之,我在 get 中创建了表单的副本,但我返回了 父亲 get,他有另一个空的副本,所以当我显示模板时,不会出现错误,因为发送的表格是空的。

有什么想法吗?谢谢。

in my way of perfectionism, I'm here to ask more questions about the not-so-well-documented class-based views.

I spend like 5 hours learning about class-based views, lurking into the code and I got a question.

Maybe what I'm trying to do is stupid, and if so, just say that.

I will put a simple example:

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)

This is a perfect valid class (it is, right?).

You have a form, and you make a GET request with a query parameter.

Works like a charm.

But lets imagine... I validate the query input to prevent some type of attack and I see that the query is malicious so I put a validation error.

With the old functions, I have a form instance (empty) and I put data in it and validation errors if needed. I always return that instance, if empty (first request) or if it filled with errors (the case of the malicious query).

The problem is with class-based views. In my get method I work with an extra instance of SearchForm so if I put validation stuff would be there and if I call get on the father it will use the instance on "form_class" that would be empty.

So, I think that there should be a way where I use the same form always, I mean: I call the request method, I pick the form_class (not create a new form), pass the data, validate and the father will return that form with the validation stuff.

Im not sure if I explained this correctly. So in short, Im creating a copy of the form in the get but I return the father get who have another copy that will be empty, so my when I display the template, there will be no errors because the form sended is empty.

Any ideas? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情定在深秋 2025-01-03 19:49:21

您的问题是 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())

Your problem is that super(SearchFormView, self).get(request, *args, **kwargs) renders its own form and own context. It's only a 3 line view function, so you should really be overriding what you need to change its behavior.

   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))

Update: alternate idea if you'd like to continue using the super call

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())
↙厌世 2025-01-03 19:49:21

问题似乎是这样一个事实:如果 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() 方法,以填充 kwargs['data'] 项,即使 HTTP 方法是 GET 也是如此。

The problem appears to be the fact that Django class based views only populate the form kwargs if the HTTP method is POST or PUT:

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

I found this a bit peculiar also, since I have on occasion used a form in a GET request (eg. a "search" form), which needed to perform some basic validation. I just override the get_form_kwargs() method on such views, to also populate the kwargs['data'] item, even when the HTTP method is GET.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文