python - 具有关系的 SQLAlchemy 继承在实例化对象中为 None

标签 python sqlalchemy mixins single-table-inheritance

我想在继承(混合)类中建立“关系”。

但是,当我创建继承对象时,关系对象是 None。我无法附加到它。

我该如何解决?

这是基于 documentation 的代码

from sqlalchemy import Column, Integer, String, DateTime, Boolean, BigInteger, Float
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()
class Target(Base):
    __tablename__ = "target"
    id = Column(Integer, primary_key=True)

class RefTargetMixin(object):
    @declared_attr
    def target_id(cls):
        return Column('target_id', ForeignKey('target.id'))

    @declared_attr
    def target(cls):
        return relationship("Target",
            primaryjoin="Target.id==%s.target_id" % cls.__name__
        )

class Foo(RefTargetMixin, Base):
    __tablename__ = 'foo'
    id = Column(Integer, primary_key=True)

print repr(RefTargetMixin.target)
print repr(Foo.target)
print repr(Foo().target)

输出是:

<sqlalchemy.orm.properties.RelationshipProperty object at 0x24e7890>
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x24e7690>
None

一般来说,我应该能够附加到关系对象(目标),但在这里我不能,因为它是 None。为什么?

最佳答案

值为 None 的原因是因为您已将此定义为多对一关系。 many-to-one,从parent-to-child,就是parent上有一个外键,只能引用一个且唯一一个child。如果您希望 RefTargetMixin 类的内容引用项目集合,则外键必须位于远程端。

因此,这里的目标是使作为 RefTargetMixin 子类的任何对象成为 Target 的潜在父类。此模式称为 polymorphic association pattern .虽然在许多 ORM 工具包中通过在 Target 上声明“多态外键”来提供此功能很常见,但这在关系上不是一个好的做法,因此答案是以某种方式使用多个表。在 examples/generic_association 文件夹中的 SQLAlchemy 核心中为此提供了三种方案,包括“带有鉴别器的单个关联表”、“每个关联表”和“每个相关表”。每个模式在这里为 RefTargetMixin 提供相同的声明模式,但表的结构发生变化。

例如,这是您使用“每个关联表”的模型,在我看来,如果您不需要一次查询多种类型的 RefTargetMixin 对象,它往往会扩展得最好(请注意,我按原样使用了示例, 只是更改了名称):

from sqlalchemy.ext.declarative import declarative_base, declared_attr
from sqlalchemy import create_engine, Integer, Column, \
                    String, ForeignKey, Table
from sqlalchemy.orm import Session, relationship

class Base(object):
    """Base class which provides automated table name
    and surrogate primary key column.

    """
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer, primary_key=True)
Base = declarative_base(cls=Base)

class Target(Base):
    pass

class RefTargetMixin(object):
    @declared_attr
    def targets(cls):
        target_association = Table(
            "%s_targets" % cls.__tablename__,
            cls.metadata,
            Column("target_id", ForeignKey("target.id"),
                                primary_key=True),
            Column("%s_id" % cls.__tablename__,
                                ForeignKey("%s.id" % cls.__tablename__),
                                primary_key=True),
        )
        return relationship(Target, secondary=target_association)

class Customer(RefTargetMixin, Base):
    name = Column(String)

class Supplier(RefTargetMixin, Base):
    company_name = Column(String)

engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)

session = Session(engine)

session.add_all([
    Customer(
        name='customer 1',
        targets=[
            Target(),
            Target()
        ]
    ),
    Supplier(
        company_name="Ace Hammers",
        targets=[
            Target(),
        ]
    ),
])

session.commit()

for customer in session.query(Customer):
    for target in customer.targets:
        print target

关于python - 具有关系的 SQLAlchemy 继承在实例化对象中为 None,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11399033/

相关文章:

Python Pulp - 将变量矩阵解决方案输出到 Excel

java - PyCharm 无法连接到网关后面的远程(java.net.UnknownHostException)

python - FastAPI SQLAlchemy 无法将字典更新序列元素 #0 转换为序列

css - 如何创建一个带有类作为变量的 Sass mixin

python - 小图和网络x

python - 在Python中删除列表中的项目

python - SqlAlchemy in_ operator with NULL

python - 使用 sqlalchemy (ORM) 进行外连接

css - Less 和 Bootstrap : how to use a span3 (or spanX [any number]) class as a mixin?

python - Flask 中的 UserMixin 是什么?