2010-04-13 107 views
1

是否有人熟悉ActiveRecord的模型「has_many:through」關係?我並不是一個真正的Rails傢伙,但這基本上是我想要做的。通過另一個聲明的sqlalchemy關係(聲明式)

作爲一個人爲的例子考慮的項目,程序員和分配:

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() 

項目有很多作業。

程序員有很多任務。 (輕描淡寫?)

但在我的辦公室至少,程序員也有不少項目 - 我想通過分配給程序員的分配可以推斷這種關係。

我希望Programmer模型有一個屬性「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聲明性語法來描述這種關係?

謝謝!

回答

2

有兩種方法我看到:

  1. 定義的關係Programmer.projectssecondary='assignment'

  2. 我將Assignment.project定義爲關係,將Programmer.projects定義爲association_proxy('assignments', 'project')(可能您還想定義創建者)。有關更多信息,請參閱Simplifying Association Object Relationships一章。

+0

$ DIFF projects.bak projects.py 30a31 >項目=關係( 「項目」,次要= '分配') ^既清晰又簡單,謝謝 – clayg 2010-04-13 19:57:06