【问题标题】:WTForms when rendering two forms on the same page with a Recaptcha fields only one is displayedWTForms 在同一页面上使用 Recaptcha 字段呈现两个表单时仅显示一个
【发布时间】:2014-07-02 22:26:36
【问题描述】:

我正在使用 Flask 和 WTforms。我也在使用 WTFRecaptcha 插件来使用验证码字段。

原来我需要在同一页面上使用两个表单。当我在每个表单上分配一个验证码字段时,其中一个验证码不会呈现在 .html 页面上。这是因为验证码总是使用相同的 ID 创建的:

我的 forms.py 文件中的验证码和表单声明:

from wtforms import PasswordField, StringField, validators, widgets, RadioField
from wtforms.form import Form
from wtfrecaptcha.fields import RecaptchaField

class FirstForm(Form):
    """First Form"""

    #Omitting fields here

    captcha_1 = RecaptchaField('Captcha', [], public_key='OMITTING_PUBLIC_KEY', private_key='OMITTING_PRIVATE_KEY', secure=True)

class Secondform(Form):
    """Second Form"""

    #Omitting fields here

    captcha_2 = RecaptchaField('Captcha', [], public_key='OMITTING_PUBLIC_KEY', private_key='OMITTING_PRIVATE_KEY', secure=True)

路线声明:

#!/usr/bin/env python

from flask import Flask, render_template, request
from flask.ext.assets import Environment
from forms import FirstForm, SecondForm
from flask import request
from flask import jsonify

@app.route('/test')
def test_form():
    """Test."""
    form_1 = FirstForm(request.form, captcha_1={'ip_address': request.remote_addr})
    form_2 = SecondForm(request.form, captcha_2={'ip_address': request.remote_addr})
    if request.method == 'POST' and (form_1.validate() or form_2.validate()) :
        return "Instructions have been sent to your e-mail"
     return render_template(
        'test-form.html',
        title='Get Started',
        form_1=form_1,
        form_2=form_2       
    )    

test-form.html

{% extends "base.html" %}

{% block content %}

    <div class="container block-form">
        <div class="row first">
            <div class="col-xs-12 col-md-7 border-right">
                <h1 class="title">{{ title }}</h1>
                <p>{{ description }}</p>
                <div class="form-area">
                    <form method="post">
                        {% for field in form_1 %}
                            <div class="form-group{% if field.errors %} has-error has-feedback{% endif %}">
                                <div class="row">
                                    <div class="col-xs-12 col-md-4">
                                        {{ field.label(class="control-label") }}
                                    </div>

                                    <div class="col-xs-12 col-md-8">
                                        {{ field(class="form-control") | safe }}
                                    </div>
                                </div>
                                {% if field.errors %}
                                    <span class="glyphicon glyphicon-remove form-control-feedback"></span>
                                {% endif %}
                                {% for error in field.errors %}
                                    <p class="help-block text-danger">
                                        <span class="glyphicon glyphicon-remove"></span>
                                        {{ error }}
                                    </p>
                                {% endfor %}
                            </div>
                        {% endfor %}
                        <br>
                        <button type="submit" class="btn btn-gradient">Submit</button>
                    </form>
                </div>
            </div>
        </div>

        <div class="row second">
            <div class="col-xs-12 col-md-7 border-right">
                <h1 class="title">{{ title }}</h1>
                <p>{{ description }}</p>
                <div class="form-area">
                    <form method="post">
                        {% for field in form_2 %}
                            <div class="form-group{% if field.errors %} has-error has-feedback{% endif %}">
                                <div class="row">
                                    <div class="col-xs-12 col-md-4">
                                        {{ field.label(class="control-label") }}
                                    </div>

                                    <div class="col-xs-12 col-md-8">
                                        {{ field(class="form-control") | safe }}
                                    </div>
                                </div>
                                {% if field.errors %}
                                    <span class="glyphicon glyphicon-remove form-control-feedback"></span>
                                {% endif %}
                                {% for error in field.errors %}
                                    <p class="help-block text-danger">
                                        <span class="glyphicon glyphicon-remove"></span>
                                        {{ error }}
                                    </p>
                                {% endfor %}
                            </div>
                        {% endfor %}
                        <br>
                        <button type="submit" class="btn btn-gradient">Submit</button>
                    </form>
                </div>
            </div>
        </div>

    </div>
{% endblock %}

form_1 中为验证码呈现的代码(直到 div 元素):

<script src="https://www.google.com/recaptcha/api/challenge?k=6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp" type="text/javascript">
//Other code here omitted
<script src="https://www.google.com/recaptcha/api/js/recaptcha.js" type="text/javascript">
//Other code here omitted
<div id="recaptcha_widget_div" class=" recaptcha_nothad_incorrect_sol recaptcha_isnot_showing_audio">

form_2 中为验证码呈现的代码(直到 div 元素):

<script type="text/javascript" src="https://www.google.com/recaptcha/api/challenge?k=6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp">
<script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha.js"/>
<div id="recaptcha_widget_div" style="display: none;"/>
<noscript><iframe src="https://www.google.com/recaptcha/api/noscript?k=6LeCJvUSAAAAAAvqwJEueVdV0wyNLPtX6KWSTdXp" 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>

结果:仅显示一个验证码。

...因此,如果我有两个验证码字段(可能在两种不同的形式上),一个不会显示。

有什么解决方案/建议吗?

【问题讨论】:

  • 您需要提供更多信息。我不知道你说的'only the first captcha shows'是什么意思,你是指在渲染的模板中吗?在处理表单提交的烧瓶视图中?请提供一个最低限度的有效示例,说明您的问题、您看到的以及您希望看到的。
  • 我很抱歉。我努力把我的问题说清楚。我编辑了这个问题。我的意思是在渲染的模板上,是的。
  • 重新提出问题,因为我发现了一个可能的问题。

标签: python recaptcha wtforms flask-wtforms


【解决方案1】:

这是一个有据可查的 Recaptcha 限制

目前,谷歌验证码机制每页只提供一个验证码表单

我鼓励您重新考虑组织页面的方式。 HTML 中的表单设计简单。围绕它们构建的大多数工具都假设一个页面只做一件事,并通过单个表单提交将结果提交给服务器。

免责声明:我对您的代码一无所知。 继续进行:听起来你的设计可能太聪明了。我的意思是,如果您还没有在其他地方看到它,并且 google 的工具不支持它,那么问题可能出在您的方法上。

如果您需要提交单个无状态事务的结果,那么 &lt;form&gt; 是合适的,而 WTForms 是生成它的好工具。如果你需要更丰富的东西,你可以考虑以下:

  • 将您的表单分成多个页面。一组简单的超链接可以提供易于导航的层次结构。
  • 使用 javascript 构建您的 DOM 并提交到 RESTful 端点(您甚至可以通过将请求正文转换为 MultiDict 来使用 WTForms 进行验证,并且 Recaptcha 支持 AJAX)
  • 使用 javascript 动态构建您的 &lt;form&gt; 并切换 action 以对应您服务器上的正确表单处理器。

【讨论】:

  • 我的页面上只需要两个表单。就是这样:) 我的表单上有两个不同的选项卡。没什么太复杂的。
  • 这就是我所说的这不是一个常见的设计。大多数基于表单的页面都有一个表单,因为您只能提交一个没有任何 javascript voodoo 的表单。
  • 我最终使用了一个表单,但使用了两个屏幕,因此我可以使用相同的验证码。非常感谢!
【解决方案2】:

reCAPTCHA 无法做到这一点。

查看相关的 ASP.NET 问题:Multiple reCAPTCHAs in one ASP.Net page

对于可能的解决方法:How do I show multiple recaptchas on a single page?

【讨论】:

  • 可以使用 reCaptcha。在您提供的第二个链接中查看我的答案。
猜你喜欢
  • 2014-03-23
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多