【问题标题】:Can I set a StringField's default value outside the field constructor?我可以在字段构造函数之外设置 StringField 的默认值吗?
【发布时间】:2018-07-29 03:22:23
【问题描述】:

如果我在字段构建过程中设置默认值,一切都会按预期工作:

my_field = StringField("My Field: ", default="default value", validators=[Optional(), Length(0, 255)])

但是,如果我尝试以编程方式设置它,它就没有效果。我尝试修改__init__ 方法,如下所示:

class MyForm(FlaskForm):
    my_field = StringField("My Field: ", validators=[Optional(), Length(0, 255)])

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.my_field.default = "set default from init"  # doesn't work

这不会设置默认值。如何以编程方式执行此操作(因为该值是基于数据库查询的动态值,如果我在 __init__ 之外执行此操作,则它不会获得最新值)?

来自我requirements.txt的相关版本:

Flask==0.12
Flask-WTF==0.14.2
WTForms==2.1

另外,如果这很重要,我正在运行 Python 3.6。

或者,我可以使用一种解决方案,该解决方案使我能够在添加新记录时在初始表单加载时设置此字段的值数据(与构造函数中指定的默认值相同的行为),但也使用相同的表单用于编辑,因此我不希望它更改已在编辑时保存/存储的对象数据。

【问题讨论】:

  • 你想做这样的事情吗? stackoverflow.com/a/51579212/5320906
  • @snakecharmerb 我想是这样,但这似乎有点不同,因为它似乎有两种不同的形式(NewForm 和 Foo),而我只有一种形式,但只想动态设置默认值对于一个领域。看看我能不能让它工作并告诉你。
  • @snakecharmerb 原来这正是我所需要的!易于实施/应用。我只是赞成它,但如果在此处发布/上下文化,我也会赞成并接受作为答案。谢谢!
  • @snakecharmerb 出于好奇,它是否也可以用于设置选择字段默认值,在表单的 init 方法中动态填充选项?
  • 已发布答案。我快速查看了在选择字段中设置选项,如果我在创建表单后设置form.field.choices 似乎可以工作,但如果我在表单的__init__ 方法中进行设置则不行。也许您可以为此提出一个单独的问题,显示您如何填充选择?感谢您在另一个答案中发现 Foo 错字。

标签: python flask python-3.6 flask-wtforms wtforms


【解决方案1】:

您可以通过将MultiDict 作为FlaskFormformdata 参数传递来设置字段的初始值。

from werkzeug.datastructures import MultiDict

class MyForm(FlaskForm):
    my_field = StringField("My Field: ", validators=[Optional(), Length(0, 255)])


form = MyForm(formdata=MultiDict({'my_field': 'Foo}))

这将在呈现表单时将my_field 输入的值设置为“Foo”,覆盖该字段的默认值。但是,当表单回传到服务器时,您不想覆盖这些值,因此您需要检查处理程序中的请求方法:

from flask import render_template, request
from werkzeug.datastructures import MultiDict

@app.route('/', methods=['GET', 'POST'])
def test():
    if request.method == 'GET':
        form = MyForm(formdata=MultiDict({'my_field': 'Foo'}))
    else:
        form = MyForm()
    if form.validate_on_submit():
        # do stuff
    return render_template(template, form=form)

【讨论】:

    【解决方案2】:

    您可以将__init__ 中的字段作为字典访问:

    class MyForm(FlaskForm):
    
      def __init__(self, *args, **kwargs):
         default_value = kwargs.pop('default_value')
         super(MyForm, self).__init__(*args, **kwargs)
         self['my_field'] = StringField("My Field: ", default=default_value,
                                        validators=[Optional(), Length(0, 255)])
    

    然后你可以这样称呼它:

    form = MyForm(default_value='Foo')
    

    有关更多信息和其他详细信息,请参阅wtforms.form.Form 类的文档。

    【讨论】:

    • 这不起作用。它说,“TypeError:字段不能添加到 Form 实例,只能添加到类。”但也许我误解了,因为我在前一个范围内声明了该字段,然后重新定义 - 只有在你获得默认 arg 时才定义它(无论如何我都需要这个字段 - 相同的表单用于添加/编辑但是默认值只能在添加时填充,这是标准行为)?我很乐意仅在使用表单添加新记录时简单地填充值数据 - 我不必使用默认构造函数选项。
    • 这个答案仍然是使用构造函数设置它,这是我试图避免的。我想构造该字段并设置其默认值 after 这样做,或者如果是空白表单(没有填充 obj,即添加新记录),至少在初始表单加载时更新它的值数据。另外,我不会总是传递那个关键字,在这种情况下会抛出一个 KeyError。
    【解决方案3】:

    回答这个问题为时已晚,但我看到了一个简单的方法来做到这一点,这在上面的答案中没有提到。最简单的赋值方法是

    @app.route('/xyz', methods=['GET', 'POST'])
    def methodName():
        form = MyForm()
        form.field.data = <default_value>
        .....
        return render_template('abc.html', form=form)
    

    当页面加载时,表单的field 将显示指定的default_value

    【讨论】:

      猜你喜欢
      • 2011-10-24
      • 1970-01-01
      • 2016-06-17
      • 2020-04-07
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      • 2011-07-12
      • 2015-04-20
      相关资源
      最近更新 更多