如何使Flask-WTFoms从标签名称列表中动态更新标签?

大卫·李斯特

我使用WTForms定义用于数据过滤的表单,其定义如下(我的目标是为用户设置BooleanFields指定的标签,我让每个用户为字段命名标签,然后将字段名称保存到Google Datastore):

class MainFilterForm(FlaskForm):
    """
    Represents main filter form.
    """

    start_date = pendulum.parse(
        str(pendulum.today().year)
        + str(pendulum.today().month)
        + '01')
    end_date = pendulum.today()
    calendar_colors_descriptions = CalendarColorsDescription(
        users.get_current_user().user_id()
        ).get_colors_description()
    search_query = StringField(
        'Search',
        [
            validators.Length(min=1, max=128),
            validators.optional()],
        default=None)
    start_date = DateField(
        'Start date',
        [validators.required()],
        format='%Y-%m-%d',
        default=start_date)
    end_date = DateField(
        'End date',
        [validators.required()],
        format='%Y-%m-%d',
        default=end_date)
    i_am_owner = BooleanField(
        'I am owner',
        default=False)
    include_all_day_events = BooleanField(
        'Include all day events',
        default=False)
    selected_colors_calendar_color = BooleanField(
        calendar_colors_descriptions[0],
        default=True)
    selected_colors_color1 = BooleanField(
        calendar_colors_descriptions[1],
        default=True)
    selected_colors_color2 = BooleanField(
        calendar_colors_descriptions[2],
        default=True)
    selected_colors_color3 = BooleanField(
        calendar_colors_descriptions[3],
        default=True)
    selected_colors_color4 = BooleanField(
        calendar_colors_descriptions[4],
        default=True)
    selected_colors_color5 = BooleanField(
        calendar_colors_descriptions[5],
        default=True)
    selected_colors_color6 = BooleanField(
        calendar_colors_descriptions[6],
        default=True)
    selected_colors_color7 = BooleanField(
        calendar_colors_descriptions[7],
        default=True)
    selected_colors_color8 = BooleanField(
        calendar_colors_descriptions[8],
        default=True)
    selected_colors_color9 = BooleanField(
        calendar_colors_descriptions[9],
        default=True)
    selected_colors_color10 = BooleanField(
        calendar_colors_descriptions[10],
        default=True)
    selected_colors_color11 = BooleanField(
        calendar_colors_descriptions[11],
        default=True)

CalendarColorsDescription类返回的字符串列表表示布尔字段的期望标签(这些值存储在Google数据存储区中)。

此表单显示在Jinja2和Flask渲染的仪表板主页上(此处仅粘贴了Flask类的相关部分):

@APP.route('/dashboard', methods=('GET', 'POST'))
def dashboard():
    """
    Main page handler, shows stats dashboard.
    """

    form = MainFilterForm()
    calendar_events = get_events(
        calendar_service,
        form.search_query.data,
        form.start_date.data,
        form.end_date.data,
        form.i_am_owner.data,
        form.include_all_day_events.data,
        form.selected_colors_calendar_color.data,
        form.selected_colors_color1.data,
        form.selected_colors_color2.data,
        form.selected_colors_color3.data,
        form.selected_colors_color4.data,
        form.selected_colors_color5.data,
        form.selected_colors_color6.data,
        form.selected_colors_color7.data,
        form.selected_colors_color8.data,
        form.selected_colors_color9.data,
        form.selected_colors_color10.data,
        form.selected_colors_color11.data)
    return flask.render_template(
        'dashboard.html',
        calendar_events=calendar_events,
        form=form)

首次运行时,所有标签均已正确设置并显示。但是,当我(通过另一种形式)更改数据存储区中的值时,除非我重新启动Web服务器,否则表单标签中的值永远不会更新。

我尝试将“调试”打印内容放到程序的不同部分,并输出从Datastore读取数据的类,并且输出始终有效并且与期望值同步。在我看来(对我来说,这完全是魔力)

form = MainFilterForm()

仅在第一个HTTP请求时执行一次(因为我也尝试将“ debug”打印内容放入MainFilterForm定义中,但仅在第一个HTTP请求时显示此打印内容)。

我尝试使用以下方法手动设置标签:

form.selected_colors_calendar_color.label = calendar_colors_descriptions[0]

下一行:

form = MainFilterForm()

但是我从Jinja2收到了错误“ TypeError:'str'对象不可调用”。

蛇魅

您采用的方法calendar_colors_descriptions在表单类的主体中分配。

这意味着它仅被评估一次(首次导入表单模块时),因此字段标签值是固定的,直到服务器重新启动为止。实际上,标签值是定义的一部分,因此在该类的所有实例之间通用

此示例代码与您的相似。

import random
import wtforms


def get_labels(labels=None):
        if labels is None:
            labels = ['red', 'amber', 'green']
        # Simulate data changes by shuffling the list.
        random.shuffle(labels)
        return labels


class StaticLabelForm(wtforms.Form):

    # labels is set when the class is compiled at import time.
    labels = get_labels()

    foo = wtforms.BooleanField(labels[0], default=True)
    bar = wtforms.BooleanField(labels[1], default=True)
    baz = wtforms.BooleanField(labels[2], default=True)

每次我们实例化new时StaticLabelForm,标签始终是相同的,因为该get_labels函数仅被调用一次。

>>> static1 = StaticLabelForm()
>>> for field in static1: print(field.label, field)
... 
<label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
<label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
<label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">

>>> static2 = StaticLabelForm()
>>> for field in static2: print(field.label, field)
... 
<label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
<label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
<label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">

我们可以通过以下方式解决此问题:将标签值传递给表单的__init__方法,然后在__init__方法内的字段上进行设置

class DynamicLabelForm(wtforms.Form):

    # Don't set the labels here
    foo = wtforms.BooleanField(default=True)
    bar = wtforms.BooleanField(default=True)
    baz = wtforms.BooleanField(default=True)

    def __init__(self, labels=None, **kwargs):
        super().__init__(**kwargs)
        # super(DynamicLabelForm, self).__init__(**kwargs) for python2!
        if labels is None:
            labels = ['red', 'amber', 'green']
        self['foo'].label = wtforms.Label(self['foo'].id, labels[0])
        self['bar'].label = wtforms.Label(self['bar'].id, labels[1])
        self['baz'].label = wtforms.Label(self['baz'].id, labels[2])

现在,标签将在每个新表单上重置:

>>> dynamic1 = DynamicLabelForm(labels=get_labels())
>>> for field in dynamic1: print(field.label, field)
... 
<label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
<label for="bar">red</label> <input checked id="bar" name="bar" type="checkbox" value="y">
<label for="baz">green</label> <input checked id="baz" name="baz" type="checkbox" value="y">

>>> dynamic2 = DynamicLabelForm(labels=get_labels())
>>> for field in dynamic2: print(field.label, field)
... 
<label for="foo">amber</label> <input checked id="foo" name="foo" type="checkbox" value="y">
<label for="bar">green</label> <input checked id="bar" name="bar" type="checkbox" value="y">
<label for="baz">red</label> <input checked id="baz" name="baz" type="checkbox" value="y">

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在PrimeFaces 5.0中使用tabView获取动态标签名称和数据?

如何使用 vue.js 在 vs-tab 中动态更改标签名称

如何在WooCommerce中更新产品属性分类标签名称

如何在Selenium Python中获取标签名称?

如何在BeautifulSoup中查找给定文本的标签名称

如何在木星中抑制标签名称

如何在Corrplot中删除标签名称

如何获得酶中的根标签名称?

为什么列表标签按字面意义使用标签名称,以及如何防止这种情况?

如何在复选框事件上访问嵌套列表视图数据模板中的标签名称

如何从输入XML获取标签值,其中标签名称存储在变量中

如何在R中为轴参数指定标签长度。我的标签名称被截断

如何使用powershell在TFS2013中获取最新的标签代码和标签名称

如何打印标签名称jsoup

jQuery:如何更改标签名称?

如何从Paypal更改标签名称

如何从Button获取标签名称?

如何删除父标签名称?

如何更改woocommerce描述标签名称

如何在新点高位图中添加动态xaxis类别标签名称

如何使用动态标签名称将数组序列化为XML

文档-如何通过标签名称获取标签的值?

如何通过标签名称和硒类查找列表元素?

如何选择从动态列表中删除特定的Li标签?

如何从打印列表的名称中获取打印标签?

在铯中,如何随时间动态更新标签?

如何在 Scala.js 中的单击事件侦听器中检索标签名称?

如何根据深度嵌套文档中的标签名称在 mongodb 中搜索键值?

无论使用C#在XML文件中的级别如何,都获取具有相同标签名称的所有标签