joinedload 和 load_only 但有过滤

joinedload and load_only but with filtering

我有两个具有简单 FK 关系的模型,Stock 和 Restriction(Restriction.stock_id FK 到 Stock)。

class Restriction(Model):
    __tablename__ = "restrictions"
    id = db.Column(db.Integer, primary_key=True)
    stock_id = FK("stocks.id", nullable=True)
    name = db.Column(db.String(50), nullable=False)

class Stock(Model):
    __tablename__ = "stocks"
    id = db.Column(db.Integer, primary_key=True)
    ticker = db.Column(db.String(50), nullable=False, index=True)

我想检索 Restriction 对象和相关的 Stock 但只有 Stock 的代码(这里省略了其他字段)。我可以简单地这样做:

from sqlalchemy.orm import *

my_query = Restriction.query.options(
    joinedload(Restriction.stock).load_only(Stock.ticker)
)
r = my_query.first()

我得到了所有限制栏,只有上面的股票代码。我可以在 SQL 查询 运行 中看到这个,我也可以访问 r.stock.ticker 并且看不到新查询 运行 因为它是急切加载的。

问题是我现在无法过滤股票,SQL如果我过滤 my_query.filter(Stock.ticker == 'GME'),Alchemy 会添加另一个 FROM 子句。这意味着有一个叉积,这不是我想要的。

另一方面,我无法使用 join 从关系中加载选定的列。即

Restriction.query.join(Restriction.stock).options(load_only(Restriction.stock))

似乎不​​适用于关系 属性。我怎样才能拥有一个过滤器并让它从关系 table?

中加载选定的列

SQL我要运行是:

 SELECT restrictions.*, stocks.ticker 
 FROM restrictions LEFT OUTER JOIN stocks ON stocks.id = restrictions.stock_id 
 WHERE stocks.ticker = 'GME'

而且我想取回一个 Restriction 对象及其股票和股票代码。这可能吗?

joinedload基本上不应该和filter一起使用。您可能需要选择 contains_eager 选项。

from sqlalchemy.orm import *

my_query = Restriction.query.join(Restriction.stock).options(
    contains_eager(Restriction.stock).load_only(Stock.ticker)
).filter(Stock.ticker == 'GME')
r = my_query.first()

因为您使用 stock_id 加入,它在结果中也会作为 Stock.idStock.ticker 旁边。但其他字段将根据您的意愿省略。

我最近写了简短的 post 如果你有兴趣的话:https://jorzel.hashnode.dev/an-orm-can-bite-you