2016-11-04 3 views
1

私は私のデータベースのモデルを作成しました:彼らは、多対多のアルバム<に関連している抽象SQLAlchemyの条件フィルタリングで

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') 

- >トラック< - >アーティスト

次に、Iこのフォームを持っている:

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)]) 

私の考えは、(必要になるが、少なくとも1つの)形の所望の組み合わせを充填して、ユーザの自由度を与えることですので、私はこの機能を、持っていますrecieves SearchForm()データ(不変辞書「FIELD_NAME」:「データ」):上記の関数でフィルタを追加するより抽象的な方法がある場合

def construct_query(form): 
    query = db.session.query(*[field.label.text for field in form if field.data and field.name != 'csrf_token']) 
    if form.search_by_album.data: 
     query = query.filter(Album.title == form.search_by_album.data) 
    if form.search_by_artist.data: 
     query = query.filter(Artist.name == form.search_by_artist.data) 
    if form.search_track.data: 
     query = query.filter(Track.title == form.search_track.data) 
    if form.year.data: 
     query = query.filter(Album.year == form.year.data) 
    result = query.all() 
    return result 

私の質問はありますか?ある日、テーブルに列を追加したり、新しいテーブルを作成したりすることにしたら、constrcut_query()にさらに怪しいifを追加しなければならなくなります。あるいは、明示的なものは暗黙的なものよりも優れているので、そのような抽象化はpythonicな方法ではありませんか?

PS 私はモデルからフォームについて知っているが、私は、彼らは私の場合であることを

答えて

1

一つの方法は、例えば、いくつかの場所でフィールドにフィルタ属性を関連付けることになるとは思いませんフォーム自体にクラスの属性として:

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 

は、新しいフィールドを追加してしまうにフィルタリングする属性フィールドの作成とその属性へのマッピングに変換するだけです。

+0

それです、サー!確かに私がやろうとしていたよりもはるかに単純でpythonic。 C#はまだ私の心が緊密に座って(神は、Pythonのインターフェイスを考えて私を許して) –

関連する問題