使用连接表继承时,Mixin 被添加到每个子类表中

发布于 2024-12-08 19:27:31 字数 458 浏览 0 评论 0原文

我有以下设置:

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

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

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

但是,Thing 和 Subthing 都将具有 Attribute mixin,这意味着它们都将具有 Attribute 中指定的列:

Thing: a | b
Subthing: a | c

我只希望这些 mixin 列出现在 Thing 而不是 Subthing 中:

Thing: a | b
Subthing: c

这可能吗?手动创建列和方法而不是对每个事物使用混合?

I have the following setup:

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

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

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

However, both Thing and Subthing will have the Attribute mixin, meaning they'll both have the columns specified in Attribute:

Thing: a | b
Subthing: a | c

I only want these mixin columns present in Thing and not Subthing:

Thing: a | b
Subthing: c

Is this possible or will I have to resort to making columns and methods manually instead of using a mixin for every Thing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤独患者 2024-12-15 19:27:31

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有ab

Subthing gets a from the parent by definition of inheritance. If you don't want that behavior, then Subthing cannot inherit from that object. A possible solution is to introduce yet another base class.

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)

Then Subthing only has column c, and Thing has a, and b.

月朦胧 2024-12-15 19:27:31

这是一种行为不一致,是由于 @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

This is a behavioral inconsistency that's developed as the result from the behavior of @declared_attr slowly deviating from a behavioral contract that was only tested against the "column copy" use case. The original use case of the "column on mixin" was to apply it to all inheriting classes equally, however @declared_attr, which was developed a bit later, didn't adopt this behavior, hence inconsistent.

Changing "column copy" to only take effect for the non-subclass is a backwards-incompatible behavioral change, so is in the upcoming 0.8 only. This is ticket #2565 (http://www.sqlalchemy.org/trac/ticket/2565) and is resolved in r9baa197f2c67.

test:

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
鱼窥荷 2024-12-15 19:27:31

我刚刚遇到了同样的问题。事实证明,如果您使用 @declared_attr 在 mixin 类中定义列,SQLAlchemy 就会正常运行。使用连接表继承时,直接在 mixin 中声明的列会泄漏到子类中。

I just ran into the same issue. It turns out if you define columns in your mixin class using @declared_attr, SQLAlchemy behaves properly. Columns declared directly in the mixin leak into sub-classes when using joined-table inheritance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文