如何在Flask / WTForms中使用populate_obj和FormField?

6

我有一个用户和一个位置信息。作为概念验证,位置信息是组合表单中的一个表单字段,应存储为用户模型。最终,我希望有大量嵌套的表单,因此我真的希望form.populate_obj(Model)负责处理数据。不过,我一定做错了什么。代码如下:

# - - - Models - - -
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(40))
    location = db.relationship('Location', backref='user')

class Location(db.Model):
    __tablename__ = 'locations'
    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(), db.ForeignKey('users.id'))
    descr = db.Column(db.String(50))

# - - - Forms - - -
class LocationForm(NoCsrfForm):
    descr = StringField('Location Name')

class CombinedForm(Form):
    username = StringField('User', validators=[DataRequired()])
    location = FormField(LocationForm)  # , default=lambda: Location())
    submit = SubmitField('Submit')

# - - - Routes - - -
@app.route('/', methods=['GET', 'POST'])
def index():
    user = User(username="not in db")
    form = CombinedForm(obj=user)
    if form.validate_on_submit():
        form.populate_obj(user)
        db.session.add(user)
        db.session.commit()
    return render_template('multi.html', form=form)

当我在索引函数中添加user.location = [Location(descr="Test")]时,我可以使用视图中的{{form.location}}渲染该字段,但是表单中对该字段的更改不会影响模型,因为populate_obj不会使用POST数据填充Location对象。当FormField在FieldList中时,填充它可以正常工作。
我缺少什么?
我找不到一个不需要FieldList的工作示例。
我已经花了很多时间在这上面,甚至当我认为自己已经弄清楚了时,我都制作了一个示例,但是我错了,至少在使用populate_list而没有FieldList时。如果有更好的处理来自2-3个模型的数据的方法,请告诉我。我快疯了,所以我真的希望得到一些帮助。谢谢你的时间。
1个回答

0

看起来我在脑海中混淆了思维,并且关系搞错了。下面的示例有效。

请注意,如果您将对象(例如User实例)传递给表单,则必须已经填好位置。如果您传递一个没有位置信息的User,则populate_obj无法在提交时从表单中找到新位置。

有没有解决这个问题的方法?

这应该作为一个FormField概念验证工作:

# - - - Models - - -
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer(), primary_key=True)
    username = db.Column(db.String(40))
    location_id = db.Column(db.Integer, db.ForeignKey('locations.id'))


class Location(db.Model):
    __tablename__ = 'locations'
    id = db.Column(db.Integer(), primary_key=True)
    descr = db.Column(db.String(50))
    users = db.relationship('User', backref='location')


# - - - Forms - - -
class LocationForm(NoCsrfForm):
    descr = StringField('Location Name')


class CombinedForm(Form):
    username = StringField('User', validators=[DataRequired()])
    location = FormField(LocationForm, default=lambda: Location())
    submit = SubmitField('Submit')


# - - - Routes - - -
@app.route('/', methods=['GET', 'POST'])
def index():
    user = User(username="Def")
    form = CombinedForm()  # don't put a user obj in unless it has a location!
    if form.validate_on_submit():
        form.populate_obj(user)
        db.session.add(user)
        db.session.commit()
    return render_template('multi.html', form=form)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接