python - 客户端部分生成表单时如何进行Flask WTForms表单验证
问题描述
我正在构建一个带有两个下拉菜单的简单用户界面。根据在第一个下拉列表中选择的内容,第二个下拉列表通过 jquery/AJAX 填充了一些新值。问题是,当提交表单时,表单验证正确地失败了,因为返回的第二个下拉列表中的选项不在首先生成下拉列表的列表中。
我已经通过在验证表单之前将从下拉列表 2 发送的任何数据注入表单对象来使其工作。这段代码如下所示,但感觉就像一个 hacky 解决方案。
form = SearchForm(request.form)
# dropdown 1
form.node_type.choices = [('default', 'Please select a node type')]
form.node_type.choices.extend([(t, t) for t in node_types()])
# dropdown 2
form.node_name.choices = [('default', 'Select a node type first')]
if request.method == 'POST':
# the below 2 lines are the hack that make it work.
node_name = request.form.get('node_name')
form.node_name.choices.append((node_name, node_name))
if form.validate():
print('hooray')
是否有标准/推荐的方式在客户端动态添加选项并且仍然让 WTForms 正确执行表单验证?
解决方案
这是一个纯 wtforms 解决方案,但应该与 flask-wtf 一起使用(flask-wtfform.validate()
在 内调用form.validate_on_submit()
)。
如果字段验证失败并出现“无效选择”错误,则代码扩展Form.validate
为调用自定义验证函数。node_name
如果验证函数返回True
,它将删除“不是有效选择”错误Form.errors
并返回True
如果Form.errors
现在为空。
import werkzeug
import wtforms
class Form(wtforms.Form):
node_type = wtforms.SelectField(choices=[(x, x) for x in 'ABCDEF'])
node_name = wtforms.SelectField(choices=[('', '')])
def validate(self):
if super().validate():
return True
invalid_choice = 'Not a valid choice'
if 'node_name' in self.errors and invalid_choice in self.errors['node_name']:
is_valid_node_name = self.cross_validate_node_name()
if is_valid_node_name:
self.errors['node_name'].remove(invalid_choice)
if not self.errors['node_name']:
del self.errors['node_name']
return not self.errors
return False
def cross_validate_node_name(self):
# Implement your validation logic here.
return self.node_type.data == 'B' and self.node_name.data == 'spam'
if __name__ == '__main__':
datas = [werkzeug.MultiDict([('node_type', 'A'), ('node_name', 'spam')]),
werkzeug.MultiDict([('node_type', 'B'), ('node_name', 'spam')])]
for data in datas:
form = Form(formdata=data)
if form.validate():
print('OK')
else:
print(form.errors)
推荐阅读
- html - 应用溢出时div不会扩展到全宽:自动
- graphql - 我真的需要用于 graphql 的 prisma ORM 吗?
- aspnetboilerplate - 如何在 Aspnetboilerplate 中用 Sqlite 替换 Sql Server?
- apache-spark - Spark并行化不均匀分区分布
- python-3.x - 我每次都必须重新启动 colaboratory 运行时吗?
- php - 验证 php 数组中内部 kery 的值?
- php - 如何在php中替换({{}})特殊字符的内容
- amazon-web-services - AWS 专用长码号发送短信失败
- javascript - 为什么 Wordpress 会阻止 js 实时聊天窗口?
- linux-kernel - 我在 yocto poky SUMO 分支上使用的是哪个 linux 内核版本?