在SQLAlchemy中有条件地过滤

时间:2015-06-26 02:22:36

标签: python sqlalchemy

有没有办法在SQL Alchemy ORM中有条件地为查询添加filter个参数?

例如,想象一下,我有以下内容:

q = session.query(X)
if a:
 q.filter(X.y == 'a')
elif b:
 q.filter(X.y == 'a', X.z == 'b')
elif c:
 q.filter(X.y == 'a', X.p == 'd') 

有没有办法说只需添加

如果X.z == 'b'

,请

b

无需在每个过滤器中读取(X.y == 'a')

似乎我可以做到

q.filter(X.y == 'a').filter(X.y == 'b')

但这会更改正在执行的查询。

2 个答案:

答案 0 :(得分:10)

尝试将您的查询收集到列表中,然后在致电*时使用filter运算符:

queries = [X.y == 'a']
if b:
    queries.append(X.z == 'b')
q.filter(*queries)

顺便说一下,我不明白为什么你认为链接两个filter会改变你的查询,它会对应X.y = a AND X.z = b,就像你使用filter(X.y == 'a', X.z == 'b')时一样。

答案 1 :(得分:-1)

我使用 Flask=1.1.2,Flask-SQLAlchemy=2.4.4 e SQLAlchemy-serializer=1.3.4.4

您必须使用 SQLAlchemy 中的 text

models.py:

from sqlalchemy_serializer import SerializerMixin

from app import db


class Planet(db.Model, SerializerMixin):
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String, nullable=False)
    rotation_period = db.Column(db.String, nullable=True)
    orbital_period = db.Column(db.String, nullable=True)
    diameter = db.Column(db.String, nullable=True)
    climate = db.Column(db.String, nullable=True)
    gravity = db.Column(db.String, nullable=True)
    terrain = db.Column(db.String, nullable=True)
    surface_water = db.Column(db.String, nullable=True)
    population = db.Column(db.Integer, nullable=True)

控制器.py

from sqlalchemy.sql import text

from app.planet.models import Planet


class ApiResource(Resource):
    @bp.route('/api/planets/')
    def get(self):
        """ Returns a list of planets """
        rows = Planet.query.order_by(Planet.name).all()

        # filters
        climate = request.args.get('climate', None)
        name = request.args.get('name', None)

        sort = request.args.get('sort', None)

        filters = None
        if climate:
            filters = "climate='" + climate + "'"
        if name:
            if filters:
                filters += " AND "
            filters += "name='" + name + "'"
        if filters:
            rows = Planet.query.filter(text(filters))

        if sort:
            rows = rows.order_by(text(sort))

        planets = list()
        for row in rows:
            planets.append(row.to_dict())

        return planets

我使用这个包 sqlalchemy_serializer 将查询的结果序列化为一个 json。