【问题标题】:Conditionally Filtering in SQLAlchemySQLAlchemy 中的条件过滤
【发布时间】:2022-05-12 01:27:09
【问题描述】:

有没有办法有条件地将filter 参数添加到 SQL Alchemy ORM 中的查询?

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

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

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

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

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

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

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

    【讨论】:

    • 这太完美了!我正在使用这个 * 运算符有条件地将多个条件传递给 or_ 函数
    【解决方案2】:

    我正在使用 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)
    

    controllers.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。

    【讨论】:

      猜你喜欢
      • 2019-12-26
      • 2018-10-15
      • 2018-08-15
      • 2022-08-24
      • 2020-10-20
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 1970-01-01
      相关资源
      最近更新 更多