我为我的数据库创建了模型:
(0, 1); (1, 0); (1, 1)
它们是多对多相关的相册< - >跟踪< - >艺术家
接下来,我有这样的表格:
class Album(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128))
year = db.Column(db.String(4))
tracklist = db.relationship('Track', secondary=tracklist,
backref=db.backref('albums',
lazy='dynamic'), lazy='dynamic')
class Track(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(128))
class Artist(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128))
releases = db.relationship('Track', secondary=releases,
backref=db.backref('artists',
lazy='dynamic'), lazy='dynamic')
我的想法是让用户自由填写所需的表单组合(但至少需要一个),所以我有了这个函数,它接收了SearchForm()。data(一个不可变的字典'field_name':'数据“):
class SearchForm(FlaskForm):
search_by_album = StringField('Album', validators=[Optional()])
search_by_artist = StringField('Artist', validators=[Optional()])
search_track = StringField('Track', validators=[Optional()])
year = StringField('Year', validators=[Optional(), Length(max=4)])
我的问题是,是否有更抽象的方法在上面的函数中添加过滤器?如果有一天我决定在我的表中添加更多列(甚至创建新表),我将不得不向constrcut_query()添加更多的怪物ifs,这最终会变得非常庞大。或者这样的抽象不是一种pythonic方式,因为“明确比隐含更好”?
PS 我从模型中了解表格,但我不认为它们是我的情况
答案 0 :(得分:1)
一种方法是将filter-attribute与某个地方的字段相关联,例如作为表单本身的类属性:
class SearchForm(FlaskForm):
search_by_album = StringField('Album', validators=[Optional()])
search_by_artist = StringField('Artist', validators=[Optional()])
search_track = StringField('Track', validators=[Optional()])
year = StringField('Year', validators=[Optional(), Length(max=4)])
# map form fields to database fields/attributes
field_to_attr = {search_by_album: Album.title,
search_by_artist: Artist.name,
search_track: Track.title,
year: Album.year}
构建查询时,您可以以一种非常舒适的方式构建where子句:
def construct_query(form):
query = db.session.query(*[field.label.text for field in form if field.data and field.name != 'csrf_token'])
for field in form:
if field.data:
query = query.filter(form.field_to_attr[field] == field.data)
# or:
# for field, attr in form.field_to_attr.items():
# if field.data:
# query = query.filter(attr == field.data)
result = query.all()
return result
添加要过滤的新字段和属性只会转换为创建字段及其到属性的映射。