2013-01-16 40 views
2

下面是一個僞多對多表結構,表示客戶訂購事件。我理想希望能夠實現的是通過使用不同的關係名稱進行隱式查詢和設置。SQLAlchemy - 使用關係按行類型進行過濾

例如(推定該初始化代碼創建相關聯的對象)

order=order() 
order.events.corporate.name = "Big Corp" 

這將設置event.type(枚舉)「企業」和event.name到「大公司」 。同樣。

print session.query(Order).filter(order.events.corporate.name == "Big Corp") 

這隻會找到具有關聯的event.type =「corporate」的事件記錄。 (簡單的例子,而不是必要的,但你的想法)

同樣使用order.events.personal.name將設置/與event.type =「個人」

你理解的幫助是什麼查詢相應記錄實現這一功能的最佳方式將非常感謝。

Base = declarative_base() 

class Order(Base): 
    __tablename__ = 'order' 
    id     = Column(Integer, primary_key=True) 
    event_id   = Column(Integer, ForeignKey('events.id')) 

    events = relationship("Events") 

class Events(Base): 
    __tablename__ = 'events' 
    order_id   = Column(Integer, ForeignKey('order.id'), primary_key=True) 
    event_id   = Column(Integer, ForeignKey('event.id'), primary_key=True) 

    corporate = relationship("Event") 
    personal = relationship("Event") 
    event  = relationship("Event") 

class Event(Base): 
    __tablename__ = 'event' 
    id     = Column(Integer, primary_key=True) 
    type    = Column(Enum('corporate', 'personal', name='enum_ev_type')) 
    name    = Column(String(32)) 

回答

3

SQLAlchemy不理解在過濾器中使用關係時的情況。在你的例子order.events.corporate中。

我有以下異常,同時試圖這樣做:

AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object associated with Order.events has an attribute 'corporate' 

我建議考慮使用SQL Alchemy Relationships documentation page描述AssociationObject模式。

所以查詢將是:

session.query(Order).filter(and_(EventsAssoc.type=="corporate",Event.name=="Big Corporation")) 

查看全部例如如何定義架構和創建對象。

from sqlalchemy import * 
from sqlalchemy import create_engine, orm 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import relationship 



metadata = MetaData() 
Base = declarative_base() 
Base.metadata = metadata 



class Event(Base): 
    __tablename__ = 'event' 
    id     = Column(Integer, Sequence("event_seq"), primary_key=True) 
    name    = Column(String(32)) 
    def __repr__(self): 
     return "%s(name=\"%s\",id=\"%s\")" % (self.__class__.__name__,self.name,self.id) 


class EventsAssoc(Base): 
    __tablename__ = 'events' 
    id     = Column(Integer, Sequence("events_seq"), primary_key=True) 
    left_id = Column(Integer, ForeignKey('order.id')) 
    right_id = Column(Integer, ForeignKey('event.id')) 

# order_id   = Column(Integer, ForeignKey('order.id'), primary_key=True) 
# event_id   = Column(Integer, ForeignKey('event.id'), primary_key=True) 
    type     = Column(Enum('corporate', 'personal', name='enum_ev_type')) 

    event = relationship(Event, backref="order_assocs") 

    def __repr__(self): 
     return "%s(events=%r,id=\"%s\")" % (self.__class__.__name__,self.event,self.id) 


class Order(Base): 
    __tablename__ = 'order' 
    id     = Column(Integer, Sequence("order_seq"), primary_key=True) 
    name = Column(String(127)) 
    events = relationship(EventsAssoc) 
    def __repr__(self): 
     return "%s(name=\"%s\",id=\"%s\")" % (self.__class__.__name__,self.name,self.id) 


db = create_engine('sqlite:////temp/test_assoc.db',echo=True) 



#making sure we are working with a fresh database 
metadata.drop_all(db) 
metadata.create_all(db) 


sm = orm.sessionmaker(bind=db, autoflush=True, autocommit=True, expire_on_commit=True) 
session = orm.scoped_session(sm) 

o = Order(name="order1") 
ea_corp = EventsAssoc(type="corporate") 
ea_corp.event = Event(name="Big Corporation") 

ea_pers = EventsAssoc(type="personal") 
ea_pers.event = Event(name="Person") 


o.events.append(ea_corp) 
o.events.append(ea_pers) 
session.add(o) 
session.flush() 

query = session.query(Order).filter(and_(EventsAssoc.type=="corporate",Event.name=="Big Corporation")) 

for order in query.all(): 
    print order 
    print order.events 

這裏是由SQLAlchemy的所產生的查詢:

SELECT "order".id AS order_id, "order".name AS order_name 
FROM "order", events, event 
WHERE events.type = ? AND event.name = ? 
('corporate', 'Big Corporation') 

PS爲了增強所述關聯對象圖案,使得所述EventsAssoc對象直接存取是可選的,SQLAlchemy的提供Association Proxy extension

+0

由於vvladymyrov。我花了一段時間纔回到這個圈子。最後,儘管這樣做並不符合我期望的風格,但我採取了設置混合屬性的方式。 –

相關問題