将重定向中的 Flask-WTForms 表单的复选框值传递回相同的表单

Passing a checkbox value from a Flask-WTForms form in a redirect back to the same form

使用 Flask 和 Flask-WTF,我想重定向到一个带有复选框的页面。 我有一个初始搜索页面,它有一个名为 "SearchForm" 的表单,在用户搜索后,我将他重定向到一个结果页面,该页面上有相同的 SearchForm,然后是结果列表视图。这使用户能够在结果页面上再次搜索。

这是我的表格:

class SearchForm(Form):
    """Search form class"""
    from app.utils.translation import Translation

    criteria = StringField(Translation.label('search'), validators=[DataRequired()])
    all_employees = BooleanField(Translation.label('all_employees'), validators=[])

现在当用户提交表单时,我可以像这样实例化它:

form = SearchForm(request.form)

我可以使用(例如)获取数据:

form.data['all_employees']

如果我不选中该复选框,WTForms 会正确地将 all_employees 解析为 False。 我重定向到具有相同表单的结果页面,我想用用户刚刚提交的数据呈现该表单。所以我这样做:

return redirect(url_for('employees.search',
                        criteria=form.data["criteria"],
                        all_employees=form.data["all_employees"]
                        ))

在搜索表单上,我使用查询字符串 (URL) 变量再次实例化表单:

form = SearchForm(request.args)

现在的问题是,因为 form.data['all_employees'] 有一个值 "False",复选框被选中。这当然是 HTML 的正常行为,只有选中复选框时才会传递复选框值。因此,如果有一个值(并且 "False" 一个值),复选框将被选中。

我可以在我的重定向中使用类似的方法解决这个问题:

all_employees='y' if form.data['all_employees'] else ''

但这意味着我必须不断地为每个重定向中的每个复选框字段执行此操作。我有很多类似的屏幕想用这种方式实现。

我可以想象 WTforms 也可以以某种方式解析复选框的 "falsy" 值,并且在这些情况下不选中该框,但即使可能,我也找不到任何文档。

我还考虑过在结果页面上处理它,如果值为 "falsy",则从 request.args 集合中删除一个变量,但这也感觉很笨拙。

也许还有另一种我不知道的方法,或者我的解决方法只是用复选框处理重定向的方法,我不知道,但在我看来这是一个非常常见的用例,Flask-WTForms 可能会有某种解决方案。

如有任何建议,我们将不胜感激。

编辑

问题更大;我刚刚注意到使用以下代码将一个空字符串传递到我的重定向:

all_employees='y' if form.data['all_employees'] else ''

然后使用以下方法实例化和呈现表单:

form = SearchForm(request.args)

将空复选框呈现为:

<input id="include_inactive" name="include_inactive" type="checkbox" value="">

因此,之后再次检查它,会将一个空字符串传回给Flask,所以当一个复选框被取消选中一次时,它会在之后呈现一个空值,并且永远无法再次检查。

在最基本的情况下,urlencoded 字符串 otherdata=value&all_employees=False 从 HTML 复选框的角度来看是一个真值。

WTForms 大部分 遵循HTML 表单和表单数据的规则。然而,由于这个布尔值是一个常见的小问题,您 可以 使用 false_values 关键字参数自定义它来定义 'falsey' 值...您可以false_values 包含字符串 False.

另一种方式,更 'HTML spec friendly' 会是这样的帮手:

def url_for_form(urlname, form, **kwargs):
    for field in form:
        if field.data:  # would exclude blank strings too
            kwargs[field.name] = field.data

    return url_for(urlname, **kwargs)

用法类似于 url_for_form('blah.search', form, otherparam=9)

如果您需要选择特定的字段,那么您可以稍微不同地设计它。