问题
I am struggling with two problems,
1/ QuerySelectField not populated
2/ Translate error if field is filled in
I have an add function and an edit function, I am using "from wtforms_alchemy.fields import QuerySelectField" to allow a choice from one data base model to be available in a drop down list. In the "addboilercircuit" function this works, in the form a drop down list is displayed and I can submit the form. in the "editboilercircuit" function I am using formpopulate_obj all the fields are populated accept the QuerySelectField, a drop down list is visible but it does not display the saved choice, if I select one of the choices and then submit I get a translate error message. Here is my code:
form.py
def boiler_ID():
return Boilers.query
class AddBoilerCircuitForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
boiler_ID = QuerySelectField('Boiler_ID',
query_factory=boiler_ID,
get_label='id')
submit = SubmitField('Register')
models.py
class Boilers(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
state = db.Column(db.String(9))
def __repr__(self):
return '<Boilers {}>'.format(self.id)
class Boilercircuit(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
boiler_ID = db.Column(db.String(30))
def __repr__(self):
return '<Boilercircuit {}>'.format(self.id)
boilers.py
@bp.route('/boilers/editboilercircuit/<int:id>', methods=('GET', 'POST'))
@login_required
def editboilercircuit(id):
obj = Boilercircuit.query.get(id) or Boilers()
form = AddBoilerCircuitForm(request.form, obj=obj)
if form.validate_on_submit():
form.populate_obj(obj)
db.session.add(obj)
db.session.commit()
flash('Congratulations, you are have updated a Boiler Circuit!')
return redirect(url_for('boilers.boilercircuits'))
return render_template('boilers/editboilercircuit.html', title= 'edit boilercircuit',
form=form, obj=obj)
and the html editboilercircuit.html
<h2>Edit Boiler Circuit</h2>
<form action="" method="post">
{{ form.hidden_tag() }}
<div>{{ form.name.label }} {{ form.name(class="input") }}</div>
<div>{{ form.boiler_ID.label }} {{ form.boiler_ID(class="input") }}</div>
<div>{{ form.submit(class="submit") }}</div>
<form>
the error message is
AttributeError: 'Boilers' object has no attribute 'translate'
on the "addboilercircuit" function this works fine, accept in my view function I have to add str to each QuerySelectField to avoid a "translate error" here is my code
def addboilercircuit():
form = AddBoilerCircuitForm()
if form.validate_on_submit():
boilercircuit = Boilercircuit(name=form.name.data,
boiler_ID=str(form.boiler_ID.data), #here I have added "str"
I have searched all the forums for a similar problem but most relate to an add function, this has helped me clean upmy code (Thanks @sean) and many others. I hope my question is clear Thanks in advance
Paul
回答1:
The key thing to take in here is that the ORM backed fields actually deal in ORM objects, not scalar values for the value of the processed form fields. The evidence of that is in the query callable that you pass to the QuerySelectField
constructor:
def boiler_ID():
return Boilers.query
That is a query that returns Boilers
instances, not integer ID values.
To sort it, add a relationship
field on to your model called boiler
and associate your form field to that. We also need to add a foreign key on boilercircuit.boiler_ID
so the relationship can establish a join path to the boilers
table.
# adds a `ForeignKey` constraint to `boiler_ID` and a `boiler`
# relationship to your `BoilerCircuit` object.
class Boilercircuit(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
boiler_ID = db.Column(db.String(30), db.ForeignKey("boilers.id"))
boiler = db.relationship("Boilers")
def __repr__(self):
return '<Boilercircuit {}>'.format(self.id)
Then modify the form:
# renames the `boiler_ID` field to `boiler` and also the field's label.
class AddBoilerCircuitForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
boiler = QuerySelectField('boiler',
query_factory=boiler_ID,
get_label='id')
submit = SubmitField('Register')
You'll also need to change any references that you made to AddBoilerCircuitForm.boiler_ID
throughout your views and templates as that field no longer exists on the form.
来源:https://stackoverflow.com/questions/58383945/flask-wtforms-queryselectfeld-form-populate-obj-fields-not-populated-and-if-fill