20

次のようなモデルがあるとします。

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    hometown = db.Column(db.String(140))
    university = db.Column(db.String(140))

ニューヨークからユーザーのリストを取得するには、次のクエリを実行します。

User.query.filter_by(hometown='New York').all()

USC に行くユーザーのリストを取得するには、次のクエリを実行します。

User.query.filter_by(university='USC').all()

そして、ニューヨークから USC に行くユーザーのリストを取得するには、次のクエリを実行します。

User.query.filter_by(hometown='New York').filter_by(university='USC').all()

ここで、変数の値に基づいてこれらのクエリを動的に生成したいと思います。

たとえば、私の変数は次のようになります。

    {'hometown': 'New York'}

またはこのように:

    {'university': 'USC'}

...またはこのように:

    [{'hometown': 'New York'}, {'university': 'USC'}]

入力として辞書 (または辞書のリスト) を受け取り、正しい sqlalchemy クエリを動的に構築する関数を作成するのを手伝ってくれませんか?

キーワードに変数を使用しようとすると、次のエラーが発生します。

key = 'university'
User.query.filter_by(key='USC').all()

InvalidRequestError: Entity '<class 'User'>' has no property 'key'

次に、複数の filter_by 式を動的に連鎖させる方法がわかりません。

明示的に filter_by 式を呼び出すことはできますが、変数に基づいて複数を連結するにはどうすればよいでしょうか?

これがより理にかなっていることを願っています。

ありがとう!

4

3 に答える 3

57

SQLAlchemyfilter_byはキーワード引数を取ります:

filter_by(**kwargs)

つまり、この関数を使用すると、任意のキーワード パラメータを指定できます。これが、コードで必要なキーワードを使用できる理由です。SQLAlchemy は基本的に、引数を値の辞書と見なします。キーワード引数の詳細については、 Python チュートリアルを参照してください。

そのため、SQLAlchemy の開発者は、任意のキーワード引数を辞書形式で受け取ることができます。しかし、あなたは反対のことを求めています:任意のキーワード引数の束を関数に渡すことができますか?

Python では、 unpackingと呼ばれる機能を使用してできることがわかりました。**単純に引数の辞書を作成し、次のように を前に付けて関数に渡します。

kwargs = {'hometown': 'New York', 'university' : 'USC'}
User.query.filter_by(**kwargs)
# This above line is equivalent to saying...
User.query.filter_by(hometown='New York', university='USC')
于 2013-10-21T23:12:13.897 に答える
2

filter_by(**request.args)ページネーションなど、モデル以外のクエリ パラメータがある場合はうまく機能しませんpage。それ以外の場合は、次のようなエラーが発生します。

InvalidRequestError: Entity '<class 'flask_sqlalchemy.MyModelSerializable'>' has no property 'page'

モデルにないクエリパラメーターを無視する次のようなものを使用します。

    builder = MyModel.query
    for key in request.args:
        if hasattr(MyModel, key):
            vals = request.args.getlist(key) # one or many
            builder = builder.filter(getattr(MyModel, key).in_(vals))
    if not 'page' in request.args:
        resources = builder.all()
    else:
        resources = builder.paginate(
            int(request.args['page'])).items

という列を持つモデルを考えるとvalid、次のようなものが機能します。

curl -XGET "http://0.0.0.0/mymodel_endpoint?page=1&valid=2&invalid=whatever&valid=1"

invalid無視され、pageページネーションに使用でき、何よりも、次の SQL が生成されます。WHERE mymodel.valid in (1,2)

(このボイラープレート保存モジュールを使用する場合は、上記のスニペットを無料で入手してください)

于 2015-01-02T12:44:30.893 に答える