gpt4 book ai didi

python - 从抽象类继承SQLAlchemy类时抛出异常: metaclass conflict: the metaclass of a derived class must be

转载 作者:太空宇宙 更新时间:2023-11-03 14:45:43 29 4
gpt4 key购买 nike

以下代码是具有一个简单表的 SqlAlchemy ORM 的非常简单的实现。 Mytable 类试图从 BaseAbstract 继承。

代码抛出以下异常:

Message: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

from abc import ABC
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

class BaseAbstract(ABC):
"""description of class"""

SQLALCHEMY_DATABASE_URI =\
'mssql+pyodbc://(local)/TestDB?driver=SQL+Server+Native+Client+11.0'
SQLALCHEMY_TRACK_MODIFICATIONS = False

engine = create_engine(SQLALCHEMY_DATABASE_URI, echo=True)
Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()
metadata = Base.metadata

class Mytable(Base, BaseAbstract):
__tablename__ = 'myTable'

id = Column(Integer, primary_key=True)
firstNum = Column(Integer, nullable=False)
secondNum = Column(Integer, nullable=False)

如果将类声明行更改为

Mytable 类(基础):

代码可以正常工作。此外,如果您将 class BaseAbstract(ABC): 更改为 class BaseAbstract(object):,代码将再次正常工作。我如何从 SQLAlchemy 中的抽象类继承?

最佳答案

Mixing metaclasses is not easy你应该避免它。 SQLAlchemy 提供了一种方法来处理 abstract base classesaugmenting the base ,另一方面,您尝试做的事情看起来很像 mixin .

您可以使用 __abstract__ 指示 SQLAlchemy 跳过为类创建表和映射器的过程:

Base = declarative_base()

class BaseAbstract(Base):
"""description of class"""
__abstract__ = True

class Mytable(BaseAbstract):
...

你也可以 augment the Base class :

class BaseAbstract:
"""description of class"""

Base = declarative_base(cls=BaseAbstract)

class Mytable(Base):
...

但在我看来,最简单的解决方案是完全放弃使用“抽象基础”并将其视为 mixin ,正如您已经在某种程度上所做的那样:

class CommonMixin:
"""description of class"""

Base = declarative_base()

class Mytable(CommonMixin, Base):
...

但是如果您坚持使用实际的abc.ABC 抽象基类,register您的模型类作为虚拟子类:

class BaseAbstract(ABC):
"""description of class"""

Base = declarative_base()

@BaseAbstract.register
class Mytable(Base):
...

缺点是 @abc.abstractmethod 修饰的方法在实例化虚拟子类时不会被检查。

如果以上不能满足您的需求,并且您想使用 ABC 来检查所需的方法是否已实现,您可以尝试按照异常指示进行操作,并创建一个新的元类,该元类是组合DeclarativeMetaABCMeta :

In [6]: class DeclarativeABCMeta(DeclarativeMeta, abc.ABCMeta):
...: pass
...:

In [7]: Base = declarative_base(metaclass=DeclarativeABCMeta)

In [8]: class BaseAbstract(abc.ABC):
...: @abc.abstractmethod
...: def foo(self):
...: pass
...:

In [13]: class MyTable(Base, BaseAbstract):
...: __tablename__ = 'mytable'
...: id = Column(Integer, primary_key=True)
...:

In [14]: MyTable()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-14-1686a36a17c6> in <module>()
----> 1 MyTable()

TypeError: "Can't instantiate abstract class MyTable with abstract methods foo"

In [18]: class MyOtherTable(Base, BaseAbstract):
...: __tablename__ = 'myothertable'
...: id = Column(Integer, primary_key=True)
...: def foo(self):
...: return 'bar'
...:

In [19]: MyOtherTable()
Out[19]: <__main__.MyOtherTable at 0x7f01b4b592b0>

不过我不能保证这一点。它可能包含很多惊喜。

关于python - 从抽象类继承SQLAlchemy类时抛出异常: metaclass conflict: the metaclass of a derived class must be,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49581907/

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