Skip to main content
 首页 » 编程设计

python之django-recaptcha 不验证输入

2025年05月04日20mfryf

我正在尝试将 django-recaptcha 与 django-registration 集成。我已经确保 django 注册有效。然后我根据它的文档(django-recaptcha 0.0.6)安装和配置 django-recaptcha。

我在 registration/forms.py 的 RegistrationForm 类中添加了 captcha = ReCaptchaField() 如下:

from captcha.fields import ReCaptchaField 
 
class RegistrationForm(forms.Form): 
    required_css_class = 'required' 
    username = forms.RegexField(regex=r'^[\w.@+-]+$', max_length=30, label=_("Username"), error_messages={'invalid': _("This value may contain only letters, numbers and @/./+/-/_ characters.")}) 
    email = forms.EmailField(label=_("E-mail")) 
    password1 = forms.CharField(widget=forms.PasswordInput, label=_("Password")) 
    password2 = forms.CharField(widget=forms.PasswordInput, label=_("Password (again)")) 
 
    captcha = ReCaptchaField() 
 
    ... 

验证码确实显示了,但是无论我在验证码文本中输入了什么(什么都不输入,正确或不正确),在按下“底部”后,它总是显示“此字段是必需的。” (当然我已经输入了两个密码字段)。

这不应该是私钥/公钥问题,因为设置不正确验证码不会显示,而是错误文本。有什么想法吗?

顺便说一句,我使用 python 2.7 和 django 1.4.3。我测试了两个浏览器:chrome 和 IE9。

[更新]

我发现这个问题的根本原因是因为我输入的文本没有传递到 POST 请求,如下所示:

POST:<QueryDict: {u'username': [u'test123'], u'password1': [u'123'], u'csrfmiddlewaretoken': [u'BUvEURhlUMYDx1DjztgdRuK1CrI7WanY'], u'email': [u'test@gmail.com'], u'password2': [u'123']}>, 

在客户端浏览器上显示的html源代码如下所示。通常它应该在 POST 请求中有“recaptcha_challenge_field”,但我不确定为什么客户端浏览器不在 POST 请求中发送这个变量。我是 java 脚本的新手。有什么想法吗?

<!doctype html> 
<html> 
    <head> 
        <title>Register for an account</title> 
    </head> 
    <body> 
 
<table> 
    <form method='post' action=''><div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='BUvEURhlUMYDx1DjztgdRuK1CrI7WanY' /></div> 
        <tr class="required"><th><label for="id_username">Username:</label></th><td><input id="id_username" type="text" name="username" maxlength="30" /></td></tr> 
<tr class="required"><th><label for="id_email">E-mail:</label></th><td><input type="text" name="email" id="id_email" /></td></tr> 
<tr class="required"><th><label for="id_password1">Password:</label></th><td><input type="password" name="password1" id="id_password1" /></td></tr> 
<tr class="required"><th><label for="id_password2">Password (again):</label></th><td><input type="password" name="password2" id="id_password2" /></td></tr> 
<tr class="required"><th><label for="id_captcha">Captcha:</label></th><td><script type="text/javascript"> 
    var DjangoRecaptchaOptions = { 
  "lang": "en" 
}; 
    if (typeof RecaptchaOptions !== 'object') { 
        RecaptchaOptions = DjangoRecaptchaOptions; 
    } else { 
        for (key in DjangoRecaptchaOptions) { 
            RecaptchaOptions[key] = DjangoRecaptchaOptions[key]; 
        } 
    } 
</script> 
<script type="text/javascript" src="https://www.google.com/recaptcha/api/challenge?k=6LeuNO4SAAAAAAdkaCUi6ybtISPI-YhIlOadgFNF&hl=en"></script> 
<noscript> 
  <iframe src="https://www.google.com/recaptcha/api/noscript?k=6LeuNO4SAAAAAAdkaCUi6ybtISPI-YhIlOadgFNF&hl=en" height="300" width="500" frameborder="0"></iframe><br /> 
  <textarea name="recaptcha_challenge_field" rows="3" cols="40"></textarea> 
  <input type='hidden' name='recaptcha_response_field' value='manual_challenge' /> 
</noscript> 
</td></tr> 
        <tr><td></td><td><input type="submit" value="Send activation email" /></td> 
    </form> 
</table> 
 
    </body> 
</html> 

请您参考如下方法:

我找到答案了!这是因为 <table> registration_form.html 中的标签,由 django-registration 包提供。内容是:

{% extends "registration/registration_base.html" %} 
{% load i18n %} 
{% block title %}{% trans "Register for an account" %}{% endblock %} 
{% block content %} 
<table> 
    <form method='post' action=''>{% csrf_token %} 
        {{ form }} 
        <tr><td></td><td><input type="submit" value="{% trans "Send activation email" %}" /></td> 
    </form> 
</table> 
{% endblock %} 

不幸的是,recaptcha 有另一个 <table>标记嵌入在其 java 脚本中,这意味着将有 recaptcha <table> registration_form 内的标签 <table>标签。尽管浏览器可以正确呈现页面,但是它无法正确检索嵌入式 <table> 中的“recaptcha_challenge_field”和“recaptcha_response_field”等字段。

解决方案是删除 <table>来自 registration_form.html 的相关标签。