在同一页面渲染两个WTForms时Recaptcha字段仅显示一个
我正在使用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>
结果:只显示了一个验证码。
... 所以如果我有两个验证码字段(可能在两个不同的表单中),其中一个就不会显示。
有没有什么解决办法或建议?
2 个回答
0
这在reCAPTCHA中是不可能实现的。
可以看看相关的ASP.NET问题:在一个ASP.Net页面中使用多个reCAPTCHA
还有一些可能的解决办法:我该如何在一个页面上显示多个reCAPTCHA?
2
这是一个关于Recaptcha的已知限制。
目前,谷歌的验证码机制每个页面只能提供一个验证码表单。
我建议你重新考虑一下页面的组织方式。HTML中的表单设计得很简单。大多数围绕表单构建的工具都假设一个页面只做一件事,并通过一次表单提交将结果发送到服务器。
免责声明:我对你的代码并不了解。不过我还是要说:感觉你的设计可能有点过于复杂。我的意思是,如果你没有在其他地方见过类似的做法,而谷歌的工具又不支持,那问题可能出在你的思路上。
如果你需要提交一个单一的无状态事务,那么使用一个<form>
是合适的,WTForms是生成它的好工具。如果你需要更复杂的功能,可以考虑以下几点:
- 把表单分成多个页面。简单的超链接可以提供一个易于导航的层次结构。
- 用JavaScript构建你的DOM,并提交到一个RESTful接口(你甚至可以通过将请求体转换成
MultiDict
来使用WTForms进行验证,而Recaptcha也支持AJAX)。 - 用JavaScript动态构建你的
<form>
,并将action
切换到对应的服务器表单处理程序。