sqlalchemy 通过另一个关系(声明性)

发布于 2024-08-28 21:28:47 字数 2203 浏览 5 评论 0原文

有人熟悉 ActiveRecord 的“has_many :through”模型关系吗?我并不是一个真正的 Rails 爱好者,但这基本上就是我想要做的。

作为一个人为的例子,考虑项目、程序员和作业:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from sqlalchemy import Column, ForeignKey
from sqlalchemy.types import Integer, String, Text
from sqlalchemy.orm import relation

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class Assignment(Base):
    __tablename__ = 'assignment'
    id = Column(Integer, primary_key=True)
    description = Column(Text)

    programmer_id = Column(Integer, ForeignKey('programmer.id'))
    project_id = Column(Integer, ForeignKey('project.id'))

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

    def __repr__(self):
        return '<Assignment("%s")>' % self.description

class Programmer(Base):
    __tablename__ = 'programmer'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))

    assignments = relation("Assignment", backref='programmer')

    def __init__(self, name=name):
        self.name = name

    def __repr__(self):
        return '<Programmer("%s")>' % self.name

class Project(Base):
    __tablename__ = 'project'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    description = Column(Text)

    assignments = relation("Assignment", backref='project')

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

    def __repr__(self):
        return '<Project("%s", "%s...")>' % (self.name, self.description[:10])

engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

项目有许多作业。

程序员有很多任务。 (轻描淡写?)

但至少在我的办公室,程序员也有许多项目 - 我希望通过分配给程序员的作业来推断这种关系。

我希望程序员模型有一个属性“项目”,它将通过分配模型返回与程序员关联的项目列表。

me = session.query(Programmer).filter_by(name='clay').one()
projects = session.query(Project).\
    join(Project.assignments).\
    join(Assignment.programmer).\
    filter(Programmer.id==me.id).all()

如何使用 sqlalchemy 声明性语法清楚、简单地描述这种关系?

谢谢!

Is anyone familiar with ActiveRecord's "has_many :through" relations for models? I'm not really a Rails guy, but that's basically what I'm trying to do.

As a contrived example consider Projects, Programmers, and Assignments:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from sqlalchemy import Column, ForeignKey
from sqlalchemy.types import Integer, String, Text
from sqlalchemy.orm import relation

from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()

class Assignment(Base):
    __tablename__ = 'assignment'
    id = Column(Integer, primary_key=True)
    description = Column(Text)

    programmer_id = Column(Integer, ForeignKey('programmer.id'))
    project_id = Column(Integer, ForeignKey('project.id'))

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

    def __repr__(self):
        return '<Assignment("%s")>' % self.description

class Programmer(Base):
    __tablename__ = 'programmer'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))

    assignments = relation("Assignment", backref='programmer')

    def __init__(self, name=name):
        self.name = name

    def __repr__(self):
        return '<Programmer("%s")>' % self.name

class Project(Base):
    __tablename__ = 'project'
    id = Column(Integer, primary_key=True)
    name = Column(String(64))
    description = Column(Text)

    assignments = relation("Assignment", backref='project')

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

    def __repr__(self):
        return '<Project("%s", "%s...")>' % (self.name, self.description[:10])

engine = create_engine('sqlite://')
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

Projects have many Assignments.

Programmers have many Assignments. (understatement?)

But in my office at least, Programmers also have many Projects - I'd like this relationship to be inferred through the Assignments assigned to the Programmer.

I'd like the Programmer model to have a attribute "projects" which will return a list of Projects associated to the Programmer through the Assignment model.

me = session.query(Programmer).filter_by(name='clay').one()
projects = session.query(Project).\
    join(Project.assignments).\
    join(Assignment.programmer).\
    filter(Programmer.id==me.id).all()

How can I describe this relationship clearly and simply using the sqlalchemy declarative syntax?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

苦笑流年记忆 2024-09-04 21:28:47

我看到有两种方法:

  1. 使用secondary='assignment'定义关系Programmer.projects

  2. 我将 Assignment.project 定义为关系,将 Programmer.projects 定义为 association_proxy('assignments', 'project') (可能是你) d 还想定义一个创建者)。请参阅简化关联对象关系一章了解更多信息。

There are two ways I see:

  1. Define a relation Programmer.projects with secondary='assignment'.

  2. I define Assignment.project as relation and Programmer.projects as association_proxy('assignments', 'project') (probably you'd also like to define a creator). See Simplifying Association Object Relationships chapter for more information.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文