【问题标题】:Way to pass information from a GET parameter to a POST form in django?将信息从 GET 参数传递到 django 中的 POST 表单的方法?
【发布时间】:2020-06-04 22:05:11
【问题描述】:

我有一个邮件列表系统,用户可以在其中单击链接取消订阅。此链接在 GET 参数中包含用户的电子邮件,并且它指向的页面包含请求反馈的简短表单。此反馈需要指向提交它的用户的电子邮件。

我尝试实现的方法是:

  1. 从 GET 参数中获取电子邮件
  2. 将其作为initial 值放在反馈表单的隐藏字段中
  3. 在发送表单时从表单数据中检索它

问题是,如果这个隐藏字段没有被禁用,用户可以干预它的值并伪装自己的身份,甚至声称反馈来自另一个用户。但是,如果我将该字段设置为禁用,则 request.POST 字典根本不包含该字段。
我还尝试启用该字段并检查它在form.changed_data 中的存在,但它似乎总是存在,即使它的值没有改变。

这是表单类:

class UnsubscribeForm(forms.Form):
    reason = forms.ChoiceField(choices=UnsubscribeFeedback.Reasons.choices)
    comment = forms.CharField(widget=forms.Textarea, required=False)
    user_email = forms.CharField(widget=forms.HiddenInput, required=False, disabled=False)

当方法为 GET 时,这就是我在视图中填充 user_email 的方式:

email = request.GET.get("email", "")
# ...
context["form"] = UnsubscribeForm(initial={"user_email": email})

请注意,我还尝试在此行之后手动禁用该字段,以及在表单的 init 方法中。结果是一样的:如果该字段被禁用,则该值不会被传递。
设置初始值后,我对其进行了 print() 以确保设置正确,并且确实如此。我还检查了页面的源代码,它正确显示了该值。

当接收到数据绑定表单时,这就是我在视图的 POST 部分检查值的方式:

form = UnsubscribeForm(request.POST)

if form.is_valid():  # This passes whether I change the value or not.
    if "user_email" in form.changed_data:  # This too passes whether I change the value or not.
        print("Changed!")

    email = form.cleaned_data["user_email"]  # This is "" if user_email is disabled, else the correct value.

我不知道为什么当该字段被禁用时我设置的初始值会被忽略。据我所知,无论任何更改,禁用的字段都会传递初始值,但这里根本没有传递初始值。正如我上面所概述的,我不能让用户可以编辑这个字段,即使它是隐藏的。

Django 是 3.0.3 版,如果这很重要的话。

有什么解决办法吗?这是一个错误吗?

【问题讨论】:

  • 您是否需要表单中的电子邮件字段?使用request.user.email在你的视图中获取用户的电子邮件不是更省钱吗?
  • 用户没有登录网站,没有登录系统,所以请求本身不包含相关信息。
  • 我明白了。仅当您向表单实例提供初始数据时检查更改的数据才有效,例如form = UnsubscribeForm(request.POST, initial={...})。因此,您需要帖子视图中的电子邮件。但是你不需要它的形式。简而言之:恕我直言,您的方法行不通。
  • 如果我可以通过禁用输入的初始数据传递数据,我不需要检查更改的数据——这是我最初的方法。根本就没有办法检索这些数据吗?如果是这样,如果隐藏字段只能在用户也可以干预的情况下使用,那么隐藏字段有什么用?
  • 不确定,但是否有可能添加基于电子邮件的哈希令牌和要检查的密钥?

标签: django post django-forms hidden-field disabled-input


【解决方案1】:

我找到了解决问题的方法,虽然它并不能完全回答为什么禁用字段会忽略运行时初始值的问题,所以从某种意义上说,这个问题仍然有待解答。

在最初的问题中,我严重忽略了指定(为了使代码最小化和可重现)包含用户电子邮件地址的 GET 请求还包含我使用不可预测的数据生成的令牌,以验证电子邮件是真实的并且对应于订阅用户。为了成功干预电子邮件,用户还必须伪造一个有效的令牌,这不太可能(也不值得付出努力),除非他们可以访问我的数据库和代码库(在这种情况下,我遇到的问题比反馈表)。

我将简单地保持隐藏字段未禁用并传递令牌,以验证地址确实有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    • 2013-06-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多