2013-04-16 41 views
0

讓我們假設我有三個表。SQLAlchemy column_property存在於表

class A(Base): 
    id = Column(Integer, primary_key=True) 
    bs = association_proxy("a_b", "b") 

class B(Base): 
    id = Column(Integer, primary_key=True) 
    extra = Column(String(10), nullable=True) 
    as = association_proxy("a_b", "a") 

class A_B(Base): 
    __table_args__ = (
    UniqueConstraint('a_id', 'b_extra'), 
    ) 
    a_id = Column(Integer, ForeignKey('A.id'), primary_key=True) 
    b_id = Column(Integer, ForeignKey('B.id'), primary_key=True) 
    b_extra = column_property(
    select([B.extra]).where(B.id=b_id) 
    ) 
    b = relationship("B", backref="a_b") 
    a = relationship("A", backref="a_b") 

和數據庫架構:

CREATE TABLE A (
    id INT(11) NOT NULL AUTO_INCREMENT, 
    PRIMARY KEY (id) 
) 
CREATE TABLE B (
    id INT(11) NOT NULL AUTO_INCREMENT, 
    extra INT(11) NOT NULL, 
    PRIMARY KEY (id) 
) 
CREATE TABLE A_B (
    a_id INT(11) NOT NULL, 
    b_id INT(11) NOT NULL, 
    b_extra INT(11) NOT NULL, 
    UNIQUE KEY ('a_id', 'b_extra'), 
    KEY a_id, 
    KEY b_id, 
    CONSTRAINT FOREIGN KEY ('b_extra') REFERENCES 'B' ('extra'), 
    CONSTRAINT FOREIGN KEY ('b_id') REFERENCES 'B' ('id'), 
    CONSTRAINT FOREIGN KEY ('a_id') REFERENCES 'A' ('id') 
) 

的想法是,A_B在B額外的數據A和B之間的關聯表是不是每B個獨特的,但它是獨特每A.我遇到的問題是,當我嘗試運行腳本時,我得到Key Error: b_extra。我已經嘗試過所有我能想到的骯髒技巧,但是我對如何解決這個問題感到茫然。

編輯:爲了說明問題,我希望column_property存在於數據庫中,並像正常一樣參與更新和插入。

這是一個稍微簡化的例子,它來自真正的應用程序,因爲它太複雜而不能在這裏發佈。

回答

0

這裏的問題在於你的A_B表有一個名爲「b_extra」的列,但是在你的A_B映射上,你用一個列屬性覆蓋了「b_extra」,它嘗試在不同的表上加載不同的列, 「B.extra」。

這裏的意圖不明確,但似乎你會擺脫A_B.b_extra,因爲它似乎並不像你想寫任何東西。或者,如果您確實希望B.extra和A_B.b_extra同時存在,則需要將這兩個表達式映射到不同的名稱。

A_B.b_extra列屬性也有點奇怪,因爲在會話過期之間,它不會與關聯到該屬性的路由保持同步,這只是some_a_b.b.extra。

+0

我想要的是讓A_B.b_extra與B.extra同步,無論是在表格還是模型中。這是因爲我可以有表級別的唯一約束,所以B.extra每A是唯一的,但不是每B。 – Dwilson

+0

然後您需要分別映射它們,並且每當關聯A和B時使用事件來更新A_B.b_extra列一起。最簡單的做法是在'A_B'的'__init __()'方法中,但如果您想要更多的靈活性,可以使用[驗證器](http://docs.sqlalchemy.org/en/rel_0_8/orm /mapper_config.html#simple-validators)或[before_flush](http://docs.sqlalchemy.org/en/rel_0_8/orm/events.html#sqlalchemy.orm.events.SessionEvents.before_flush)等等,取決於當你需要更新這個值時。 – zzzeek

+0

'before_flush'看起來很有希望,但文檔有點混亂。你有關於如何使用它的例子嗎? – Dwilson