【发布时间】:2021-11-05 15:35:30
【问题描述】:
我正在构建一个使用 SQLAlchemy 的 Python 应用程序,并且我正在尝试在自定义声明性基类与其自身之间实现多对多关系(自引用)。但我无法让它工作。我在下面附上代码以及错误回溯,以防有人可以提供帮助:) 模型的所有实体都已经从这个基类扩展,并且应用程序到目前为止正在运行,以防万一。
谢谢!!
代码(非功能性):
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from sqlalchemy import MetaData, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy import String
permissions = Table(
'permissions', MetaData(),
Column('origin_id', String, ForeignKey('bases.id'), primary_key=True),
Column('target_id', String, ForeignKey('bases.id'), primary_key=True)
)
class Base:
__tablename__ = 'bases'
__table_args__ = {
'mysql_engine': 'InnoDB'
}
id = Column(String, primary_key=True)
targets = relationship(
'Base',
secondary='permissions',
primaryjoin='Base.id == permissions.c.origin_id',
secondaryjoin='Base.id == permissions.c.target_id',
backref='origins'
# Reference:
# https://docs.sqlalchemy.org/en/14/orm/join_conditions.html#self-referential-many-to-many
)
Base = declarative_base(cls=Base)
追溯:
class ContactMethod(Base):
File "/usr/local/lib/python3.8/site-packages/SQLAlchemy-1.4.23-py3.8-linux-x86_64.egg/sqlalchemy/orm/decl_api.py", line 72, in __init__
_as_declarative(reg, cls, dict_)
File "/usr/local/lib/python3.8/site-packages/SQLAlchemy-1.4.23-py3.8-linux-x86_64.egg/sqlalchemy/orm/decl_base.py", line 126, in _as_declarative
return _MapperConfig.setup_mapping(registry, cls, dict_, None, {})
File "/usr/local/lib/python3.8/site-packages/SQLAlchemy-1.4.23-py3.8-linux-x86_64.egg/sqlalchemy/orm/decl_base.py", line 177, in setup_mapping
return cfg_cls(registry, cls_, dict_, table, mapper_kw)
File "/usr/local/lib/python3.8/site-packages/SQLAlchemy-1.4.23-py3.8-linux-x86_64.egg/sqlalchemy/orm/decl_base.py", line 299, in __init__
self._scan_attributes()
File "/usr/local/lib/python3.8/site-packages/SQLAlchemy-1.4.23-py3.8-linux-x86_64.egg/sqlalchemy/orm/decl_base.py", line 511, in _scan_attributes
raise exc.InvalidRequestError(
sqlalchemy.exc.InvalidRequestError: Mapper properties (i.e. deferred,column_property(), relationship(), etc.) must be declared as @declared_attr callables on declarative mixin classes. For dataclass field() objects, use a lambda:
【问题讨论】:
-
你想用这个实现什么?所有类都应该有自己的 M-N 关系吗?还是所有类之间的通用 M-N 关系?或者完全是别的什么?
-
你能听从我回答中给出的建议吗?
-
@van 我希望能够设置模型的任意两个实体之间的关系,因此这将是所有类之间的通用 M-N 关系。到目前为止还没有工作...
-
好吧,在这种情况下,你真的应该考虑使用Inheritance。 声明性 Base 的目的与在继承方面拥有基础对象不同。
-
谢谢@van!虽然我也试过。首先通过创建一个继承自 Base 的类并合并这种关系,以便所有其他类都继承自这个新类。另外,我尝试创建一个Mixin,以便所有类首先从 Base 继承,然后从 Mixin 继承。这些都不起作用......
标签: python python-3.x sqlalchemy