使用Flask-SQLAlchemy查询

3 投票
3 回答
20866 浏览
提问于 2025-04-18 17:26

我正在使用Flask来构建一个RESTful API,并用SQLAlchemy将我的应用程序连接到MySQL数据库。

在数据库中,我有两个模型:Order(订单)和Order_line(订单行)。一个订单由多个订单行组成。每个订单行都有一个状态。

我在把SQL请求转换成Flask-SQLAlchemy语句时遇到了困难,尤其是关于连接(join)的部分。

以下是我的模型:

class Order(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    date_created = db.Column(db.DateTime)
    lines = db.relationship('Order_line',
                            backref=db.backref('order',
                                               lazy='join'))
    def __init__(self, po):
        self.date_created = datetime.datetime.now()

class Order_line(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    order_id = db.Column(db.Integer, db.ForeignKey('order.id'))
    status_id = db.Column(db.Integer, db.ForeignKey('status.id'))

    def __init__(self, order_id):
        self.order_id = order_id
        self.status_id = 1

class Status(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    short_name = db.Column(db.String(60))
    description = db.Column(db.String(400))
    lines = db.relationship('Order_line',
                            backref=db.backref('status',
                                               lazy='join'))

    def __init__(self, short_name, description):
        self.short_name = short_name
        self.description = description

基本上,我想获取所有的订单(也就是获取Order.id),这些订单中至少有一个订单行的状态ID不是1。

对应的SQL查询语句是:

SELECT id FROM `order`
INNER JOIN order_line
    ON order.id=order_line.order_id
WHERE
    order_line.status_id NOT LIKE 1
GROUP BY
    order.id

我找不到将这个SQL语句转换成SQLAlchemy命令的方法。我对Flask-SQLAlchemy的封装和普通SQLAlchemy之间的区别感到特别困惑。

3 个回答

1

也可以使用

db.session.query(Order.id).filter(Order.lines.status_id != 1 ).group_by(Order.id).all()
2

我也是刚开始接触Flask-SQLAlchemy,但最近为了我的应用程序学了很多东西。这里有一些可能对你有帮助的点:

现在在进行查询时,'vanilla'(原生)SQLAlchemy和Flask-SQLAlchemy之间的主要区别在于Flask-SQLAlchemy是如何处理会话变量的。在Flask版本中,你有一个db对象来管理你的会话,像这样:

  db = SQLAlchemy()

通过这个对象,你可以进行查询。在你的情况下,你可以这样执行查询:

db.session.query(Order).filter(Order.id==Order_line.order_id).filter(Order_line.status_id!=1).group_by(Order.id).all()

这不是完全一样的查询,但非常相似。它会返回Order表中的所有字段,但如果你只想要“id”,可以在查询语句中把“Order”改成“Query.id”。至于你提到的“like”过滤器,我不太确定在Flask-SQLAlchemy中怎么实现,但我找到一个问题,里面有关于原生SQLAlchemy的答案:如何在SQLAlchemy ORM查询中使用not like操作符

3

你可以使用 .any() 方法:

Order.query.filter(Order.lines.any(Order_line.status_id != 1))

撰写回答