【问题标题】:How to append errors to form's "non_field_errors" from view?如何从视图中将错误附加到表单的“non_field_errors”?
【发布时间】:2026-01-08 21:00:01
【问题描述】:

这是我的情况。我有一个网页供用户创建自己的帐户。在这个页面上,有 reCaptcha 来防止机器人。一旦用户单击“提交”,在相应视图中构建相应表单之前,将执行 reCaptcha 验证。假设用户的输入未通过 reCaptcha 验证。我应该如何将此错误提示给用户?我应该将错误添加到表单的“non_field_errors”吗?如果是这样,这样做的正确方法是什么?

我目前的方法是将错误列表(包括 reCaptcha 错误)从视图传递到表单构造函数,并将错误添加到 init() 中的表单的 non_field_errors 中。然而,我向表单的 non_field_errors (referenced post) 添加错误的方式是不够的。当传递的列表中有多个错误时,后一个总是覆盖它之前的一个。 如何将错误附加到表单的 non_field_errors 而不是每次都覆盖现有的?

views.py:

def create_account(request):
    """ User sign up form """
    if request.method == 'POST':
        recaptcha_result = check_recaptcha(request)
        if recaptcha_result.is_valid:
            ...
        else:
            non_form_errors = ['Incorrect reCaptcha word entered. Please try again.'];
            signup_form = SignUpForm(request.POST, non_form_errors=non_form_errors)
    else:
        signup_form = SignUpForm()

    public_key = settings.RECAPTCHA_PUBLIC_KEY
    script = displayhtml(public_key=public_key)

    return render(request, 'create_account.html', 
        {'signup_form': signup_form, 'script': script})

forms.py:

class SignUpForm(UserCreationForm):
""" Require email address when a user signs up """
email = forms.EmailField(label='Email address', max_length=75, widget=TextInput(attrs={'size': 30}))

def __init__(self, *args, **kwargs):
    non_form_errors = []
    if kwargs.has_key('non_form_errors'):
        non_form_errors.append(kwargs.pop('non_form_errors'))

    super(SignUpForm, self).__init__(*args, **kwargs)

    for err in non_form_errors:
        self.errors['__all__'] = self.error_class(err)

【问题讨论】:

  • 为什么表单中没有验证码?你可以使用类似field/widget classes的东西。
  • @lazerscience - 感谢您指出更好的方向。 :)

标签: django django-forms django-views


【解决方案1】:

forms.py试试这个:

def __init__(self, *args, **kwargs):
    non_form_errors = []
    if kwargs.has_key('non_form_errors'):
        non_form_errors.append(kwargs.pop('non_form_errors'))

    super(SignUpForm, self).__init__(*args, **kwargs)
    errors = self.errors.get('__all__', [])
    for err in non_form_errors:
        errors.append(self.error_class(err))
    self.errors['__all__'] = errors

【讨论】:

  • 谢谢克雷格。但由于代码的可重用性更好,我决定采用@lazerscience 建议的方法。
【解决方案2】:

首先,我要感谢 @lazerscience 为解决我的问题指出了更好的方向。但是,我没有按照建议采用 django-recaptcha 应用程序。

我最终使用了 Marco Fucci 的 code snippet。快速总结一下,此代码 sn-p 可帮助您为 ReCaptcha 创建自定义表单字段(和小部件)。一旦完成,您只需在表单定义中添加一行即可在表单上添加 ReCaptcha。

【讨论】:

    最近更新 更多