我想在继承(混合)类中建立“关系”。
但是,当我创建继承对象时,关系对象是 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/