gpt4 book ai didi

python - 具有具体继承的 SQLAlchemy 多态关系

转载 作者:太空狗 更新时间:2023-10-30 00:57:19 26 4
gpt4 key购买 nike

我正在使用 SQLAlchemy 的具体表继承。在声明式模型类中,我已成功配置它。

我的代码就像:

class Entry(AbstractConcreteBase, db.Model):
"""Base Class of Entry."""

id = db.Column(db.Integer, primary_key=True, nullable=False)
created = db.Column(db.DateTime, nullable=False)
post_id = declared_attr(lambda c: db.Column(db.ForeignKey("post.id")))
post = declared_attr(lambda c: db.relationship("Post", lazy="joined"))

@declared_attr
def __tablename__(cls):
return cls.__name__.lower()

@declared_attr
def __mapper_args__(cls):
# configurate subclasses about concrete table inheritance
return {'polymorphic_identity': cls.__name__,
'concrete': True} if cls.__name__ != "Entry" else {}

class TextEntry(Entry):
"""Text and Article Entry."""

text = db.deferred(db.Column(db.Text, nullable=False))

class PhotoEntry(Entry):
"""Photo Entry."""

path = db.deferred(db.Column(db.String(256), nullable=False))

在 shell 中测试它时工作正常:

>>> from models.entry import Entry
>>>
>>> Entry.query.all()
[<PhotoEntry 'Title' created by tonyseek>,
<PhotoEntry 'TITLE 2' created by tonyseek>,
<PhotoEntry 'Title 3' created by tonyseek>,
<PhotoEntry 'Title 4' created by tonyseek>,
<TextEntry 'Title' created by tonyseek>]

然后我在其他模型中设置关系时遇到了麻烦。每个条目都有一个外键post_id来加入Post模型,但我无法在Post中定义反向引用。那行不通:

class Post(db.Model):
"""An Post."""

id = db.Column(db.Integer, primary_key=True, nullable=False)
description = db.Column(db.Unicode(140), nullable=False)
entries = db.relationship(Entry, lazy="dynamic")

它抛出了一个异常并说:

InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Original exception was: Class 'models.entry.Entry' is not mapped.

显然 Entry 是一个抽象类,不能映射到真实存在的表。官网文档有例子,但是它的基类不是抽象的。现在应该如何设置与抽象模型的多态关系?

最佳答案

我已经找到问题的原因和解决方法。

根据sqlalchemy官网的文档,抽象类可以是一个映射类,因为polymorphic_union函数可以创建一个虚表。

我使用的是声明式模型,不是手工构建映射器,所以虚拟表pjoin不应该是手工创建的。基类 AbstractConcreteBase 有一个方法 __delcare_last__ 会创建带有 polymorphic_union 函数的 pjoin,但它会在事件 after_configured 触发。

PostEntry的关系会在Post类生成后创建,此时事件after_configured 没有被触发,所以 __delcare_last__ 函数还没有创建虚拟表 pjoin 并将其映射到 Entry。所以异常“Class 'models.entry.Entry' is not mapped.”将被提高。

现在,我重构Post模型,让它在__delcare_last__函数中创建与Entry的关系,那么它就会成功,因为触发的事件和映射的 Entry

我新实现的类是这样的:

class Post(db.Model):
"""An Post."""

id = db.Column(db.Integer, primary_key=True, nullable=False)
description = db.Column(db.Unicode(140), nullable=False)

@classmethod
def __declare_last__(cls):
cls.entries = db.relationship(Entry, viewonly=True)

def attach_entries(self, entries):
"""Attach Entries To This Post.

Example:
>>> post = Post("An Interesting News", "Wow !!!")
>>> text_entry = TextEntry(*t_args)
>>> photo_entry = PhotoEntry(*p_args)
>>> post.attach_entries([text_entry, photo_entry])
>>> len(post.entries)
2
>>> db.session.commit()
>>>
"""
for entry in entries:
self.entries.append(entry)
entry.post = self
db.session.add(entry)

关于python - 具有具体继承的 SQLAlchemy 多态关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9223630/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com