SQLAlchemy:部分指定的关系

Che*_*evy 5 python ddl sqlalchemy foreign-keys

我试图用 SQLAlchemy 描述遗留 SQL 模式中存在的关系。我将架构翻译为:

class Lang(Base):
    __tablename__ = "tblLang"
    id = Column("ID", Integer, primary_key=True)
    # ...

class ItemName(Base):
    __tablename__ = "tblItemName"
    # ItemName has a composite primary key
    id = Column("ID", Integer, primary_key=True)
    lang_id = Column("Lang", Integer, ForeignKey("Lang.id"), primary_key=True)
    name = Column("Name", String)

class Item(Base):
    __tablename__ = "tblItem"
    id = Column("id", Integer, primary_key=True)
    inventory = Column("Inventory", Integer)
    # item_name_id specifies only part of the table
    # relationship
    item_name_id = Column("ItemNameID", Integer, ForeignKey("tblItemName.ID"))
    # lang_id should come from outside the database:
    # a user preference stored in a configuration file
    # or a session cookie, etc.
    item_name = relationship(???)
Run Code Online (Sandbox Code Playgroud)

也就是说,我们有一组已知的语言。对于每个项目,可能有一种或多种语言的项目名称,但lang_id我们应该选择的项目名称将由外部参数给出。

我希望能够创建一个在查询执行之前设置该值的查询对象。

我的问题是:我应该用什么来代替???上面的代码中的 才能创建这样的查询,以及我应该如何指定lang_id执行时间之前?


编辑:

根据@sanyash评论,如下:这是我希望能够获得的示例查询:

SELECT tblItemName.Name, tblItem.Inventory
FROM tblItem 
  LEFT JOIN tblTiemName 
    ON tblItemName.ID = tblTiem.NameID 
    AND tblItem.Lang = :lang
Run Code Online (Sandbox Code Playgroud)

:lang已设置为(2从用户偏好中获取)

当写类似这样的东西时:

query = session.query(Item).with_entities([
    Iten.c.item_name.name, 
    Item.c.inventory
])
Run Code Online (Sandbox Code Playgroud)

Che*_*evy 0

警告:这是一种解决方法,可能不是最佳的,甚至不是正确的

我找不到能让关系如我所愿的神奇咒语。相反,我可以写一个解决方法:

from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method


class Item(Base):
    __tablename__ = "tblItem"
    id = Column("id", Integer, primary_key=True)
    inventory = Column("Inventory", Integer)

    @hybrid_method
    def item_name(self, lang):
        return ItemName.query.filter(
            ItemName.id == self.id,
            ItemName.lang_id == lang
        )

    @hybrid_property
    def item_names(self):
        return ItemName.query.filter(ItemName.id == self.id)
Run Code Online (Sandbox Code Playgroud)

然后我可以像这样使用它:

item_names = Item.get(123).item_names.all()
item_klingon_name = Item.get(123).item(KLINGON_LANG_ID).one()
Run Code Online (Sandbox Code Playgroud)

我完全意识到这不是一个正确的解决方案,并且它不进行急切加载。我什至不确定我在这种情况下是否正确使用@hybrid_methodand@hybrid_property

我发布这个答案是希望它可以使某些用例受益,但我会很乐意接受其他解决方案,最好是使用relationship.