I have a User with a Location. Just as proof of concept the Location is a FormField within the CombinedForm which should be stored as a User Model. Eventually I want to have a fairly large number of nested forms so I would really like form.populate_obj(Model) to take care of processing the data. However, I must be doing something wrong. Here is my code:
# - - - 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)
When I add user.location = [Location(descr="Test")]
to the index function I can render the field using {{ form.location }}
in my view, but changes to the field in the form don't have an effect on the model, since populate_obj does not populate the Location object with the POST data. When the FormField is inside a FieldList, populating it works.
What am I missing?
I've been unable to find a working FormField example without FieldList.
I've spent a lot of time on this, even made an example when I thought I had figured it out, but I was wrong, at least when using FormField with populate_list without FieldList. If there is a better approach to processing data from 2-3 Models in one Form please let me know. I'm going crazy so I would really appreciate some help. Thanks for your time.
It seems like I got really mixed up in my head and got the relationships wrong. The example below works.
Note that if you do pass an object, like a User instance, to the form, it hast to already have the location populated. If you pass a User without a location, populate_obj fails to find the new location from the Form on submission.
Is there a way around that?
This should work as a FormField proof of concept:
# - - - 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)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.