2011-10-06 38 views
0

當被添加到每個子類表,我有以下設置:密新加入了使用表繼承

class Attribute(object): 
    a = Column(Integer) 

class Thing(Base, Attribute): 
    b = Column(Integer) 

class Subthing(Thing): 
    c = COlumn(Integer) 

然而,無論事情和Subthing將有屬性混入,這意味着他們倆已經指定的列在屬性:

Thing: a | b 
Subthing: a | c 

我只希望目前在東西和這些混入列不Subthing:

Thing: a | b 
Subthing: c 

這是可能的,還是我將不得不求助於手動創建列和方法,而不是爲每個事情使用混合?

+1

這看起來完全正常的對我說:Subthing從事情,從屬性繼承繼承。爲什麼Subthing不會從它的父類繼承? –

+0

另外,Thing也是繼承的「基礎」是什麼? –

+0

在單一表連接和連接表繼承的情況下,對我來說沒有實際意義。屬性將被無故覆蓋。 –

回答

4

Subthing根據繼承的定義從父項得到a。如果您不想要這種行爲,則Subthing不能從該對象繼承。一個可能的解決方案是引入另一個基類。

class Attribute(object): 
    @declared_attr # the actual syntax on SQLAlchemy for doing mixins 
    def a(cls): 
     return Column(Integer) 

class BaseThing(Base): 
    pass 

class Thing(BaseThing, Attribute): 
    b = Column(Integer) 

class Subthing(BaseThing): 
    c = Column(Integer) 

然後Subthing只有列c,以及東西有ab

0

我剛碰到同樣的問題。事實證明,如果您使用@declared_attr定義了mixin類中的列,則SQLAlchemy的行爲會正確。在使用連接表繼承時,直接在mixin中聲明的列會泄漏到子類中。

1

這是一個行爲不一致性,它是由於@declared_attr的行爲慢慢背離僅針對「列副本」用例進行測試的行爲契約而產生的。 「mixin專欄」的最初用例是將它同樣應用於所有繼承類,但稍後開發的@declared_attr不採用此行爲,因此不一致。

將「列副本」更改爲僅對非子類生效是一種向後不兼容的行爲更改,因此僅在即將到來的0.8版中。這是票#2565(http://www.sqlalchemy.org/trac/ticket/2565),並在r9baa197f2c67解決。

測試:

from sqlalchemy import * 
from sqlalchemy.ext.declarative import declarative_base, declared_attr 

Base = declarative_base() 

class Mixin(object): 
    a = Column(Integer) 

    @declared_attr 
    def b(cls): 
     return Column(Integer) 

class A(Mixin, Base): 
    __tablename__ = 'a' 
    id = Column(Integer, primary_key=True) 

class B(A): 
    __tablename__ = 'b' 
    id = Column(Integer, ForeignKey('a.id'), primary_key=True) 

assert 'a' in A.__table__.c 
assert 'b' in A.__table__.c 
assert 'a' not in B.__table__.c 
assert 'b' not in B.__table__.c