在我的应用程序中,一个“ 设置”可以与多个“ 产品”相关联。针对一组列出的产品必须定义数量。对于这种多对多关系,我遵循SQLAlchemy documentation使用带有附加列(quantity
)的关联表。
使用下面包含的代码,我能够使用Flask-WTF生成的表单成功更新表中的现有(手动输入)数据,但无法添加新的“关联”。我收到以下错误:
TypeError: populate_obj: cannot find a value to populate from the
provided obj or input data/defaults
我怀疑是因为python无法定位/没有set_id
的值。当我print(form.data)
时,我看到以下输出:
'products': [{'product_id': 1, 'quantity': '105', 'csrf_token': '...'}, {'product_id': 2, 'quantity': '123', 'csrf_token': '...'}, {'product_id': 4, 'quantity': '120', 'csrf_token': '..'}]
您是否同意可能缺少对set.id
的引用?我尝试在主表单类set.id
中包含一个SetForm()
字段,但这没有用。是否可以通过某种方式将其传递给populate_obj()
还是应该通过像这样遍历表单数据来“手动”完成?
for item in form.products.entries:
product = Product.query.filter_by(id=item.data['product_id'])
set = Set.query.get(id)
association = Set_Product_Association(set=set, product=product, quantity=data['quantity']
db.session.add(association)
(希望是)相关的代码位:
forms.py
class SetProdForm(FlaskForm):
product_id = SelectField('Product', coerce=int)
quantity = TextField()
def __init__(self, *args, **kwargs):
super(SetProdForm, self).__init__(*args, **kwargs)
self.product_id.choices = [(product_id.id, product_id.part_number)
for product_id in Product.query.order_by(Product.part_number).all()]
class SetForm(FlaskForm):
...
products = FieldList(FormField(SetProdForm), min_entries=3)
submit = SubmitField('Update')
models.py
class Set_Product_Association(db.Model):
__tablename__ = 'set_product_association'
set_id = db.Column(db.Integer, db.ForeignKey('sets.id'), primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('products.id'), primary_key=True)
quantity = db.Column(db.Integer)
product = db.relationship("Product", back_populates="sets")
set = db.relationship("Set", back_populates="products")
class Set(db.Model):
__tablename__ = 'sets'
id = db.Column(db.Integer, primary_key=True)
products = db.relationship("Set_Product_Association",
back_populates="set")
class Product(db.Model):
__tablename__= 'products'
id = db.Column(db.Integer, primary_key=True)
part_number = db.Column(db.String(100), unique=True, nullable=False)
sets = db.relationship("Set_Product_Association",
back_populates="product")
views.py
@main.route('/sets/edit/<int:id>', methods = ['GET', 'POST'])
@login_required
def editSet(id):
setToBeEdited = Set.query.get_or_404(id)
form = SetForm(obj=setToBeEdited)
if form.validate_on_submit():
form.populate_obj(setToBeEdited)
db.session.add(setToBeEdited)
db.session.commit()
flash('Set definition has been updated.')
return redirect(url_for('.sets'))
return render_template('edit_set.html', form=form)