Pio*_*ost 5 python sqlalchemy sqlalchemy-continuum
当我尝试使用 SQLAlchemy-Continuum 扩展对 Kotti 项目中的表进行版本控制时,我遇到了sqlalchemy.exc.InvalidRequestError: Implicitly combining column(...)错误。这些表使用连接表继承方法来模拟继承。根据 Kotti 的原始代码,我创建了显示问题的最小测试用例(test.py如下)。该错误可以在文件内容之后的回溯中看到,如下所示:
\n\n\nsqlalchemy.exc.InvalidRequestError:在属性“transaction_id”下隐式组合列contents_version.transaction_id与列nodes_version.transaction_id。请为这些同名列显式配置一个或多个属性。
\n
正如最后一个调试行所说
\n\n\n\n\n信息:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(transaction_id, Column)
\n
很明显,错误是在配置模型transaction_id属性时发生的DocumentVersion。该模型由 SQLAlchemy-Continuum 扩展自动创建,以跟踪原始Document模型中的更改。我猜想 SQLAlchemy-Continuum 扩展不能正确处理这种情况(连接表继承),但我不知道如何解决这个问题。我已阅读 SQLAlchemy 的常见问题解答条目,标题为I\xe2\x80\x99m 收到有关 \xe2\x80\x9cImplicitly Combining X X under attribute Y\xe2\x80\x9d 的警告或错误但给出的错误来自扩展我仍然不知道在哪里可以解决这个问题。
我在此处的SQLAlchemy-Continuum 跟踪器和此处的SQLAlchemy 邮件列表上提出了此问题提出了此问题,但尚未得到回复。
\n\nSQLAlchemy-Continuum 1.2.0、SQLAlchemy 1.0.8
\n\ntest.py:
import logging\nfrom sqlalchemy import (Column, ForeignKey, Integer, String)\nfrom sqlalchemy.ext.declarative import (declarative_base, declared_attr)\nfrom sqlalchemy.orm import configure_mappers\nfrom sqlalchemy.util import classproperty\nfrom sqlalchemy_continuum import make_versioned\n\nlogging.basicConfig()\nlogging.getLogger(\'sqlalchemy.orm\').setLevel(logging.INFO)\nmake_versioned(user_cls=None)\n\nclass Node(declarative_base()):\n __versioned__ = {}\n __mapper_args__ = dict(polymorphic_on=\'type\',\n polymorphic_identity=\'node\',\n with_polymorphic=\'*\')\n\n @declared_attr\n def __tablename__(cls):\n return \'{0}s\'.format(cls.__name__.lower())\n\n id = Column(Integer(), primary_key=True)\n type = Column(String(30), nullable=False)\n\nclass Content(Node):\n __versioned__ = {}\n\n @classproperty\n def __mapper_args__(cls):\n return dict(polymorphic_identity=cls.__name__.lower())\n\n id = Column(Integer, ForeignKey(\'nodes.id\'), primary_key=True)\n\nclass Document(Content):\n __versioned__ = {}\n id = Column(Integer(), ForeignKey(\'contents.id\'), primary_key=True)\n\nconfigure_mappers()\nRun Code Online (Sandbox Code Playgroud)\n\n输出和回溯:
\n\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) _configure_property(type, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) Identified primary key columns: ColumnSet([Column(\'id\', Integer(), table=<nodes>, primary_key=True, nullable=False)])\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _configure_property(id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _configure_property(type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) inserting column to existing list in properties.ColumnProperty id\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _configure_property(id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _configure_property(type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) inserting column to existing list in properties.ColumnProperty id\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) _post_configure_properties() started\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) initialize prop id\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) initialize prop type\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) _post_configure_properties() complete\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _post_configure_properties() started\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) initialize prop id\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) initialize prop type\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _post_configure_properties() complete\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _post_configure_properties() started\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) initialize prop id\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) initialize prop type\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _post_configure_properties() complete\nINFO:sqlalchemy.orm.mapper.Mapper:(Transaction|transaction) _configure_property(issued_at, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Transaction|transaction) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Transaction|transaction) _configure_property(remote_addr, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(Transaction|transaction) Identified primary key columns: ColumnSet([Column(\'id\', BigInteger(), table=<transaction>, primary_key=True, nullable=False)])\nINFO:sqlalchemy.orm.mapper.Mapper:(Transaction|transaction) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(type, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(transaction_id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(end_transaction_id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(operation_type, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) Identified primary key columns: ColumnSet([Column(\'id\', Integer(), table=<nodes_version>, primary_key=True, nullable=False), Column(\'transaction_id\', BigInteger(), table=<nodes_version>, primary_key=True, nullable=False)])\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(Node|nodes) _configure_property(versions, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Content|contents) _configure_property(versions, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(Document|documents) _configure_property(versions, RelationshipProperty)\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions setup primary join nodes.id = nodes_version.id\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions setup secondary join None\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions synchronize pairs [(nodes.id => nodes_version.id)]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions secondary synchronize pairs []\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions local/remote pairs [(nodes.id / nodes_version.id)]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions remote columns [nodes_version.id]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions local columns [nodes.id]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:Node.versions relationship direction symbol(\'ONETOMANY\')\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(version_parent, RelationshipProperty)\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent setup primary join nodes.id = nodes_version.id\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent setup secondary join None\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent synchronize pairs [(nodes.id => nodes_version.id)]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent secondary synchronize pairs []\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent local/remote pairs [(nodes_version.id / nodes.id)]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent remote columns [nodes.id]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent local columns [nodes_version.id]\nINFO:sqlalchemy.orm.relationships.RelationshipProperty:NodeVersion.version_parent relationship direction symbol(\'MANYTOONE\')\nINFO:sqlalchemy.orm.strategies.LazyLoader:NodeVersion.version_parent lazy loading clause nodes.id = :param_1\nINFO:sqlalchemy.orm.strategies.LazyLoader:NodeVersion.version_parent will use query.get() to optimize instance loads\nINFO:sqlalchemy.orm.strategies.LazyLoader:Node.versions lazy loading clause :param_1 = nodes_version.id\nINFO:sqlalchemy.orm.mapper.Mapper:(NodeVersion|nodes_version) _configure_property(transaction, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(operation_type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(transaction_id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(end_transaction_id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(version_parent, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(transaction, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) _configure_property(id, Column)\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) inserting column to existing list in properties.ColumnProperty id\nINFO:sqlalchemy.orm.mapper.Mapper:(ContentVersion|contents_version) constructed\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(operation_type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(transaction_id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(end_transaction_id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(id, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(type, ColumnProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(version_parent, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(transaction, RelationshipProperty)\nINFO:sqlalchemy.orm.mapper.Mapper:(DocumentVersion|documents_version) _configure_property(transaction_id, Column)\nTraceback (most recent call last):\n File "/home/piotr/projects/sqlalchemy-continuum/test.py", line 38, in <module>\n configure_mappers()\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 2736, in configure_mappers\n Mapper.dispatch._for_class(Mapper).after_configured()\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/event/attr.py", line 218, in __call__\n fn(*args, **kw)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/events.py", line 550, in wrap\n fn(*arg, **kw)\n File "/home/piotr/projects/sqlalchemy-continuum/sqlalchemy_continuum/builder.py", line 165, in configure_versioned_classes\n self.build_models()\n File "/home/piotr/projects/sqlalchemy-continuum/sqlalchemy_continuum/builder.py", line 87, in build_models\n self.manager.transaction_cls\n File "/home/piotr/projects/sqlalchemy-continuum/sqlalchemy_continuum/model_builder.py", line 263, in __call__\n self.version_class = self.build_model(table)\n File "/home/piotr/projects/sqlalchemy-continuum/sqlalchemy_continuum/model_builder.py", line 250, in build_model\n args\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/api.py", line 55, in __init__\n _as_declarative(cls, classname, cls.__dict__)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 88, in _as_declarative\n _MapperConfig.setup_mapping(cls, classname, dict_)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 103, in setup_mapping\n cfg_cls(cls_, classname, dict_)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 135, in __init__\n self._early_mapping()\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 138, in _early_mapping\n self.map()\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/ext/declarative/base.py", line 529, in map\n **self.mapper_args\n File "<string>", line 2, in mapper\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 627, in __init__\n self._configure_properties()\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1318, in _configure_properties\n setparent=True)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1525, in _configure_property\n prop = self._property_from_column(key, prop)\n File "/home/piotr/projects/sqlalchemy-continuum/env/lib/python2.7/site-packages/sqlalchemy/orm/mapper.py", line 1650, in _property_from_column\n raise sa_exc.InvalidRequestError(msg)\nsqlalchemy.exc.InvalidRequestError: Implicitly combining column contents_version.transaction_id with column nodes_version.transaction_id under attribute \'transaction_id\'. Please configure one or more attributes for these same-named columns explicitly.\n\nProcess finished with exit code 1\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
1451 次 |
| 最近记录: |