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

时间:2010-04-13 14:08:20

标签: python sqlalchemy one-to-many declarative relation

是否有人熟悉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()

项目有很多作业。

程序员有很多作业。 (保守的?)

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

我希望程序员模型有一个属性“projects”,它将通过Assignment模型返回与Programmer相关的Projects列表。

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声明性语法清楚简单地描述这种关系?

谢谢!

1 个答案:

答案 0 :(得分:2)

我看到两种方式:

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

  2. 我将Assignment.project定义为关系,Programmer.projects定义为association_proxy('assignments', 'project')(可能您也想定义创建者)。有关详细信息,请参阅Simplifying Association Object Relationships章节。