我有以下设置:
class Attribute(object):
a = Column(Integer)
class Thing(Base, Attribute):
b = Column(Integer)
class Subthing(Thing):
c = COlumn(Integer)
但是,Thing和Subthing都有属性mixin,这意味着它们都有属性中指定的列:
Thing: a | b
Subthing: a | c
我只希望这些mixin列出现在Thing而不是Subthing:
Thing: a | b
Subthing: c
这是可能的还是我必须手动制作列和方法,而不是每次使用mixin?
答案 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
列,而Thing有a
和b
。
答案 1 :(得分: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
答案 2 :(得分:0)
我刚遇到同样的问题。事实证明,如果使用@declared_attr
在mixin类中定义列,则SQLAlchemy行为正常。直接在mixin中声明的列在使用连接表继承时会泄漏到子类中。