我想使用Flask、SQLAlchemy和WTForms为多对多关系创建一个表单来表示这些模型:
personaddress = db.Table('personaddress',
db.Column('person', db.Integer, db.ForeignKey('person.id')),
db.Column('address', db.Integer, db.ForeignKey('address.id'))
)
class Person(db.Model):
__tablename__ = "person"
id = db.Column(Integer, primary_key=True)
name = db.Column(String, nullable=False)
addresses = db.relationship('Address', secondary=personaddress, backref=db.backref('person', lazy='dynamic'))
class Address(db.Model):
__tablename__ = "address"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
需求
现在,我想创建一个包含表单的页面,以实现以下目标:
(人与地址之间的关系)
重要要求:使用QuerySelectField,我可以为一个人选择现有地址。但是我想以相同的形式添加新地址。
对于主模型和子表单,我使用了model_form
,使用FormField
作为连接表,但我就是想不出如何更新所有内容,包括外键关系。对于显示的所有表单和子表单,该页面应具有单个提交按钮。
问题
更轻松地处理吗
发布于 2016-03-22 17:27:19
我之前也遇到过类似的事情。我试图使用model_form来解决这个问题,但它不能完全解决动态添加新条目的问题,而且我在处理关系时很难使用它。
在WTForms中使用QuerySelectField只会帮助你填充例如。具有id的< select >,值对对应于现有地址。但它仍然在模板中呈现为常规的html形式。
通过使用某种类型的多选,可以在前端dynamically add新的选项,您可以以相同的形式发送额外的地址。如果数据库中不存在新地址,则端点将负责创建新地址。
WTForm表单将为:
from app import db
class PersonAddressForm(Form):
id = HiddenField('id')
name = StringField('Name')
addresses = QuerySelectField('Addresses',
query_factory=lambda: db.session.query(Address),
get_pk=lambda a: a.id, get_label=lambda a: a.name)
# Custom validate
def validate(self):
# ... custom validation
return True
路由类似于:
# ... this will be used to create and update a user
@route('create/<userid>', methods=["GET"])
def get_user_form(userid):
# ... Get the Person
user = Person()
if userid:
# ... if userid supplied, use existing Person object
user = Person.query.get(userid)
# ... Populate the form
person_form = PersonAddressForm(obj=user)
# ... return form
return render_template('somepage.html', form=person_form)
@route('create/<userid>', methods=["POST"])
def post_person_form(userid):
person_form = PersonAddressForm(request.form)
if person_form.validate():
# ... Get db object
person = db.session.query(Person).get(form.id)
# ... Add changes to the object from the form
person_form.populate_obj(obj=person_address)
# ... Get addresses
addresses = form.addresses.raw_data
# ... loop over and add to person
for address in addresses:
# Add or create an address
actual_address = db.session.query(Address).get(address.id)
# ... check if address is existing
if not actual_address:
# ... if address not existing, create new one
actual_address = Address(address.name)
db.session.add(actual_address)
# ... Append new or created address to person
person.addresses.append(actual_address)
# ... save changes to the db
db.session.commit()
# ... Update/Create complete
return redirect(url_for('get_users'))
else:
# ... form not valid, notify user
# ...
这将处理编辑/创建用户和创建地址。以及创建它们之间的关系。要使其也支持删除地址,请更改
person.addresses.append(actual_address)
至
person.addresses = list_of_actual_addresses
并在person模型中进行更改(cascade='delete-orphan')
addresses = db.relationship('Address', secondary=personaddress, cascade='delete-orphan' backref=db.backref('person', lazy='dynamic'))
这将使表单每次更新整个地址关系,级联将删除孤立地址。因此,每次提交表单时,都会更新一个人的整个地址列表。
在处理模板中的WTForms时,如果您还没有使用宏,我强烈建议您使用宏。您必须在某种程度上重写它,但请查看this。
希望这能有所帮助
https://stackoverflow.com/questions/25118175
复制相似问题