Python 如何设置WTForms SelectField的默认值?

Python 如何设置WTForms SelectField的默认值?,python,flask,wtforms,Python,Flask,Wtforms,当尝试使用WTForms设置SelectField的默认值时,我会像这样将值传递给'default'参数 class TestForm(Form): test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=2) 我还尝试了以下方法 class TestForm(Form): test_field = SelectField("Test: ", choices=[(1, "Abc"), (2

当尝试使用WTForms设置SelectField的默认值时,我会像这样将值传递给'default'参数

class TestForm(Form):
  test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=2)
我还尝试了以下方法

class TestForm(Form):
  test_field = SelectField("Test: ", choices=[(1, "Abc"), (2, "Def")], default=(2, "Def"))

也不要将默认选定字段设置为“Def”。这适用于其他类型的字段,如TextField。您如何设置SelectField的默认值?“

您发布的第一种方式是正确的,对我来说也适用。对它不起作用的唯一解释可能是您正在运行一个较旧版本的WTForms,它在1.0.1上对我起作用,我相信这个问题是由
字段的
数据
属性覆盖了
默认值
,而WTForms无法理解(例如,DB模型对象——它需要一个
int
)。如果您在构造函数中填充表单,则会发生这种情况,如下所示:

form = PostForm(obj=post)
解决方案是在填充表单后手动设置
数据
属性:

form = PostForm(obj=post)
form.category.data = (post.category.id
                      if page.category
                      else 0) # I make 0 my default

有几种方法可以做到这一点。您的第一个代码片段确实是正确的

但是,如果要在视图中动态执行此操作,还可以执行以下操作:

form = TestForm()
form.test_field.default = some_default_id
form.process()

这是一个带有
SelectField
choices
设置当您使用
int
时,其工作原理如下:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
或:


Flask WTF 0.14.2
user在这里。因此,这个答案适用于与我有类似问题的任何人

基本上,以前的解决方案都不能在
表单上正常运行。请在提交()时验证

在加载页面时,设置
form.test\u field.data
确实会更改默认值,但在提交
validate\u后,数据保持不变(浏览器中的用户更改无效)

设置
form.test\u字段。默认值
然后调用
form.process()
也会在加载页面时更改值,但是
validate\u on\u submit
将失败

以下是新的方法:

class TestForm(Form):
    test_field = SelectField("Test", choices=[(0, "test0"), (1, "test1")])

@app.route("/test")
def view_function():
    form = TestForm(test_field=1)
    if form.validate_on_submit():
        ...

如果您正在使用flask_wtf,并且希望为嵌套在类似下面的字段列表中的不同SelectFields设置默认值

from flask_wtf import FlaskForm


class FormWithSelect(FlaskForm):
    my_select_field = SelectField(validators=[DataRequired()], coerce=int)


class FormWithMultipleSelects(FlaskForm):
    select_fields = FieldList(FormField(FormWithSelect), min_entries=1)
    submit = SubmitField(label="save all the select field values")
解决方案是覆盖
数据
,而不是像您预期的那样覆盖
默认值

def generate_my_form(my_data, overwrite_data=True):
    form = FormWithMultipleSelects(select_fields=[{
        "my_select_field": {
             "name": d["name"],
             # ...
        }
    } for d in my_data]))
    for n range(len(form.select_fields)):
        form.select_fields[n].my_select_field.choices = [(1,'foo'), (2,'bar')]
        # I wan't 'bar' to be the option selected by default
        # form.select_fields[n].my_select_field.default = 2  # has no effect!
        if overwrite_data:
            form.select_fields[n].my_select_field.data = 2 #  works
基本上,这个解决方案与上面的类似;我只是想为更复杂的字段列表提供一个解决方案。在评论中提到,这有一个副作用:
form.validate\u on\u submit()如果您正在覆盖
数据
,则
不起作用!您可以构建一个简单的解决方法,在调用
提交时验证
以禁用对
数据的覆盖

它不是超优雅的,但很管用


PS:我的声誉太低,无法直接评论Elliot的正确答案。

我对动态设置默认选择字段有一些问题,我认为这些字段可能有用。 模型是这样的:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
形式是这样的:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
景色是这样的:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
它工作正常,并正确设置了Selectfield默认值。但我更改了如下代码:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
视图中:

@dashboard.route('/useredit', methods=['GET', 'POST'])
    @login_required
    def useredit():
        ....
        user = current_user._get_current_object()       
        form = OrganEditForm(obj=user)
         ....
以表格形式

def __init__(self, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
但是这次没有设置城市默认值。我改变了形式如下:

test_select = SelectField("Test", coerce=int, choices=[(0, "test0"), (1, "test1")], default=1)
class State(db.Model):
    __tablename__ = 'states'
    id = db.Column(db.Integer, primary_key=True)   
    name = db.Column(db.String(128), nullable=False)


class City(db.Model):
    __tablename__ = 'cities'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64))
    state_id = db.Column(db.Integer, db.ForeignKey('states.id'))   
    state = db.relationship(State, backref='state')


class User(UserMixin, db.Model):
    ...
    city_id = db.Column(db.Integer, db.ForeignKey('cities.id'))
    city = db.relationship('City', backref='city')
class UserEditForm(FlaskForm):
    ...
    state = SelectField("state", coerce=int)
    city = SelectField("city", coerce=int)
    ....

  def __init__(self, state_id, *args, **kwargs):
       super(UserEditForm, self).__init__(*args, **kwargs)
       self.state.choices =  [(state.id, state.name)
                        for state in State.query.order_by('name').all()]
       self.city.choices = [(city.id, city.name)
                            for city in   City.query.filter_by(state_id=state_id).order_by('name').all()]   
@dashboard.route('/useredit', methods=['GET', 'POST'])
@login_required
def useredit():
    ....
    user = current_user._get_current_object()       
    form = OrganEditForm(state_id=user.city.state_id, state=user.city.state_id, city=user.city_id)
     ....
def __init__(self, *args, **kwargs):
           kwargs['city'] = kwargs['obj'].city_id
           super(UserEditForm, self).__init__(*args, **kwargs)
           self.state.choices =  [(state.id, state.name)
                            for state in State.query.order_by('name').all()]
           self.city.choices = [(city.id, city.name)
                                for city in   City.query.filter_by(state_id=kwargs['obj'].city.state_id).order_by('name').all()] 
但它不起作用。我尝试了许多解决方案,最后我将city变量名更改为usercity:

usercity= SelectField("city", coerce=int)
kwargs['city']=kwargs['obj'].city\u id
to
kwargs['usercity']=kwargs['obj'].city\u id
,前提是它工作正常


问题是,当我设置
obj=user
时,city selectfield的默认值从
kwargs['obj']读取.city
是我在
用户
模型中定义的。

在运行时从视图中动态填充选项时,这是使其默认选择一个选项的正确方法。由于谷歌让很多人都来问这个问题,这可能是公认的答案。我注意到,当我更改默认选项w时在视图和提交表单的列表中使用另一个选项时,将提交默认选项,而不是新选项。如何解决此问题?这似乎不再有效。当我更新字段时,原始选项=choicesfunction()无论如何都会被调用。因此更新字段没有效果。**UPDATE**form.category.choices=[(),()]为我工作你测试过第二个变量吗?在我的系统上调用'form.test\u select.default=1'不会改变任何东西。当你使用整数ID时,强制=int是一个重要的设置。在两个窗体上设置默认值,一个有效,另一个无效。结果表明一个ID是字符串,另一个是整数。强制解决了这个问题。第二个很好,但是您必须编辑一些内容。正确的语法是
form.test\u select.process([])
。process方法需要一个迭代参数。我测试的版本是2.3.1。请注意,对于
SelectMultipleField
,默认值必须是一个列表,即:
默认值=[2]
。这篇文章的三分之二听起来像是一个问题,而不是一个答案。你能把这部分写在“解决方案是…”之后吗开始时,如果您认为有帮助,请提供背景信息?是的。这就是有效的方法。换言之:要在选择列表中选择某个特定选项,必须在首次实例化时将该选项加载到表单中。同样,要在多个选择列表中选择多个选项第一次实例化表单时,必须将选项加载到表单中。设置selectlist的语法因其类型而异:1)selectlist示例:form=MyUserForm(角色=1)#第一个选项是预选的2)selectmultiplelist示例:form=MyUserForm(角色=[1,3])#第一个和第三个选项也是我预先选择的作品!Flask WTF==0.14.3非常感谢,我甚至无法在文档中找到解决方案,非常感谢
Python Flask SelectField choices 

    # method 1 - routes.py
     form.proj_cat_id.default    = table1.proj_cat_id
     form.process()  # for preset 

    # method 2 - routes.py
    form.proj_cat_id.process_formdata([table1.proj_cat_id])



# method 3  - routes.py
      proj_cat_id_default    = table1.proj_cat_id
      return render_template('abc.html',proj_cat_id_default=proj_cat_id_default)

# method 3 - abc.html
        {% set z = form.proj_cat_id.process_data(proj_cat_id_default) %}
        {{ form.proj_cat_id(class="form-control form-control-lg") }}