2012-06-05 117 views
5

我一直在這方面一直在絞盡腦汁,似乎無法解決如何解決問題。請注意,我已經削減了很多不相關的領域的我的模型繼承+外鍵

我在編碼我的SQL-鍊金術模型的中間,也遇到了以下問題:

由於多種計費系統,每個系統具有完全不同的屬性,並且由於不同類型的訂閱屬性(即用戶名,節點位置等),我不得不走下多態繼承之路。

class Subscription(Base): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(255)) 
    secret = db.Column(postgresql.BYTEA) 
    type = db.Column(SubscriptionType.db_type()) 
    status = db.Column(StatusType.db_type()) 
    subscription_id = db.Column(db.Integer) 

    __tablename__ = 'subscription' 
    __table_args__ = {'schema':'public'} 

    __mapper_args__ = {'polymorphic_on' : type} 

    def __repr__(self): 
     return '<Subscription: %r>' % self.id 

class Product1(Subscription): 
    __mapper_args__ = {'polymorphic_identity' : SubscriptionType.product1}  
    id = db.Column(db.Integer, db.ForeignKey('public.subscription.id'), 
     primary_key = True) 
    billing_system = db.Column(
     db.Integer, 
     db.ForeignKey('public.billing_system.id') 
    ) 

class BillingSystem(Base): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(255)) 
    type = db.Column(BillingSystemType.db_type()) 

    __tablename__ = 'billing_system' 
    __table_args__ = {'schema':'public'} 

    __mapper_args__ = {'polymorphic_on' : type} 

    def __repr__(self): 
     return '<Subscription: %r>' % self.id 

class BillingSystem1(BillingSystem): 
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}  
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
     primary_key = True) 
    billing_system = db.Column(
     db.Integer, 
     db.ForeignKey('public.billing_system.id') 
    ) 
    foo = db.Column(db.Integer) 
    bar = db.Column(db.Integer) 

class BillingSystem2(BillingSystem): 
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem2}  
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
     primary_key = True) 
    billing_system = db.Column(
     db.Integer, 
     db.ForeignKey('public.billing_system.id') 
    ) 
    bing = db.Column(db.Integer) 
    boo = db.Column(db.Integer) 


    __tablename__ = 'billing_system_product2' 
    __table_args__ = {'schema':'public'} 

這一切都工作正常,除了一件事。

說我運行以下命令:

>>> a = Product1() 
>>> b = BillingSystem.objects.get(1) 
>>> a.billing_system = b 
>>> session.add(a) 
>>> session.commit() 

我會收到以下錯誤。

sqlalchemy.exc.ProgrammingError: (ProgrammingError) can't adapt type 'BillingSystem1' 'INSERT INTO 

我明白這是什麼意思,並且我嘗試了以下內容。

>>> a.billing_system = b.id 

這隻存儲ID,當我嘗試檢索關聯的對象時,我反而會收到一個整數。這涉及到我必須做一個額外的查詢。我希望這不是要走的路。

我也嘗試添加外鍵的所有計費系統ID的產品1型號

class BillingSystem1(BillingSystem): 
    __mapper_args__ = {'polymorphic_identity' : BillingSystemType.billingsystem1}  
    id = db.Column(db.Integer, db.ForeignKey('public.billing_system.id'), 
     primary_key = True) 
    billing_system = db.Column(
     db.Integer, 
     db.ForeignKey('public.billing_system.id'), 
     db.ForeignKey('public.billing_system1.id'), 
     db.ForeignKey('public.billing_system2.id'), 
    ) 
    foo = db.Column(db.Integer) 
    bar = db.Column(db.Integer) 

這還沒有在所有的工作中,我收到了同樣的ProgrammingError例外,說明該類型可以不適應。

我已經蒐羅手冊,並不能找到如何做到這一點,但我需要某種形式的神奇選項,以允許這種情況發生:

>>> a = BillingSystem.query.get(1) 
>>> type(a) 
BillingSystem 

相反的:

>>> a = BillingSystem.query.get(1) 
>>> type(a) 
BillingSystem1 

是否有人能夠闡明我如何查詢我的一組多態模型的ID,並且只獲得基礎模型的類?

我覺得這會解決我的問題,我只是不知道如何解決問題。

感謝您抽出寶貴時間閱讀本文,我真的很想知道我哪裏會出錯(我也一直覺得太久了,所以沒有幫助)。

乾杯, 里斯

+3

這可能不會成爲你的超級有用的答案,但似乎爲了找出是否我可以幫你,我會閱讀大量的代碼並找出一些細節。 在這個網站上得到答案的最好方法是將代碼削減到令人難以置信的簡單但仍然給出相同的錯誤。然後你可以問一個非常具體的問題:「爲什麼這4行代碼中的第3行會引發錯誤?」作爲額外的獎勵,你通常會在你完成這個過程時解決問題。祝你好運! –

+1

一些休息和你的建議幫助了很多!謝謝 :) –

回答

1
class Subscription(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(255)) 
    secret = db.Column(postgresql.BYTEA) 
    type = db.Column(SubscriptionType.db_type()) 
    status = db.Column(StatusType.db_type()) 
    subscription_id = db.Column(db.Integer) 

    billing_system_id = db.Column(
     db.Integer, 
     db.ForeignKey('public.billing_system.id') 
    ) 
    billing_system = db.relationship('BillingSystem', backref='subscriptions') 

所以我所做的是:

1)轉移了Subscription.billing_system_id外鍵多達新增認購基地訂閱模式 2)。billing_system關係

所以,現在我這樣做:

>>> o = BillingSystem.query.get(1) 
>>> a = Product1() 
>>> a.billing_system_id = o.id 

導致:

>>> a.billing_system.subscriptions 
[<cPanel Hosting Reseller: 2>] 
>>> a.billing_system_id 
2 

所以,除非我在這裏做得不對,它似乎工作。我只是不能通過實際的BillingSystem對象,我實際上必須設置ID。儘管保存模型時它仍然是參考性的,所以我沒有看到太多的問題。

感謝您的幫助:)