2009-10-27 62 views
3

我已經存在一個數據庫,並希望使用SQLAlchemy訪問它。因爲,數據庫結構由另一段代碼(Django ORM,實際上)管理,我不想重複自己,描述每個表結構,所以我使用了autoload自檢。我堅持一個簡單的具體表繼承。SQLAlchemy聲明式具體自動加載表繼承

Payment    FooPayment 
    + id (PK) <----FK------+ payment_ptr_id (PK) 
    + user_id    + foo 
    + amount 
    + date 

下面是代碼,與表的SQL descritions的文檔字符串:

class Payment(Base): 
    """ 
    CREATE TABLE payments(
     id serial NOT NULL, 
     user_id integer NOT NULL, 
     amount numeric(11,2) NOT NULL, 
     date timestamp with time zone NOT NULL, 
     CONSTRAINT payment_pkey PRIMARY KEY (id), 
     CONSTRAINT payment_user_id_fkey FOREIGN KEY (user_id) 
      REFERENCES users (id) MATCH SIMPLE) 
    """ 
    __tablename__ = 'payments' 
    __table_args__ = {'autoload': True} 
    # user = relation(User) 

class FooPayment(Payment): 
    """ 
    CREATE TABLE payments_foo(
     payment_ptr_id integer NOT NULL, 
     foo integer NOT NULL, 
     CONSTRAINT payments_foo_pkey PRIMARY KEY (payment_ptr_id), 
     CONSTRAINT payments_foo_payment_ptr_id_fkey 
      FOREIGN KEY (payment_ptr_id) 
      REFERENCES payments (id) MATCH SIMPLE) 
    """ 
    __tablename__ = 'payments_foo' 
    __table_args__ = {'autoload': True} 
    __mapper_args__ = {'concrete': True} 

實際的表有額外的列,但這是完全不相干的問題,所以在試圖最小化的代碼我已經簡化了所有內容。

的問題是,當我運行此:

payment = session.query(FooPayment).filter(Payment.amount >= 200.0).first() 
print payment.date 

產生的SQL是沒有意義的(注意缺少加入condidion的):

SELECT payments_foo.payment_ptr_id AS payments_foo_payment_ptr_id, 
     ... /* More `payments_foo' columns and NO columns from `payments' */ 
    FROM payments_foo, payments 
    WHERE payments.amount >= 200.0 LIMIT 1 OFFSET 0 

,當我試圖訪問payment.date我收到以下錯誤:Concrete Mapper|FooPayment|payments_foo does not implement attribute u'date' at the instance level.

我試過添加隱式外鍵引用id = Column('payment_ptr_id', Integer, ForeignKey('payments_payment.id'), primary_key=True)FooPayment w沒有任何成功。嘗試print session.query(Payment).first().user作品(我已經省略了User類和評論線)完美,所以FK內省工程。

如何在FooPayment上執行簡單查詢並從結果實例中訪問Payment的值?

我使用SQLAlchemy 0.5.3,PostgreSQL 8.3,psycopg2和Python 2.5.2。 感謝您的任何建議。

回答

4

您的表結構與聯合表繼承中使用的類似,但它們當然不對應於具體表繼承,其中父類的所有字段都在子類的表中重複。現在你有一個子類比父代少的子類和對父類實例的引用。切換到聯合表繼承(並在您的條件下使用FooPayment.amount或在繼承中放棄使用簡單聚合(參考)

按其他模型中的字段進行過濾不會自動添加聯接條件。應該用於加入你的例子,這是不可能的一般情況下確定這種情況,這就是爲什麼你必須定義關係屬性參考付款,並在過濾器中使用其has()方法來獲得正確的連接條件

+0

謝謝!在不同的繼承類型之間肯定會弄錯,簡單地刪除'{'concrete':True}'使它加入繼承,並且它完美地工作。感謝解釋。 – drdaeman 2009-10-28 13:06:50