如何为继承自SQLAlchemy声明基类的类定义元类

9

我使用的是Python 2.6和sqlalchemy 0.6.1

这就是我想要做的:

from sqlalchemy.types import (
    Integer,
    String,
    Boolean
)
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class SampleMeta(type):
    def __new__(cls, name, bases, attrs):
        attrs.update({   'id': Column('Id', Integer, primary_key=True),
                    'name': Column('Name', String),
                    'description': Column('Description', String),
                    'is_active': Column('IsActive', Boolean)
                })
        return super(SampleMeta, cls).__new__(cls, name, bases, attrs)

class Sample(Base):
    __tablename__ = 'Sample'
    __table_args__ = {'useexisting': True}
    __metaclass__ = SampleMeta

    def __init__(self, id, name, description, is_active):
        self.id = id
        self.name = name
        self.description = description
        self.is_active = is_active

    def __repr__(self):
        return "<(%d, '%s', '%s', %r)>" % (self.id, self.name, self.description, self.isactive)

And the error I am getting is this:

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

现在,如果我按照上面的方法使用:
class Sample(object)

替代

class Sample(Base)

它的工作绝对正常。

我需要动态更新类的属性,因此我将使用动态属性和列名称。为了能够实现这一点,我需要上述代码片段正常工作。

请帮忙!

2个回答

8

要使用元类,它必须从DeclaredMeta继承。但是在这种情况下,不需要元类。使用混合即可:

from sqlalchemy.types import (
    Integer,
    String,
    Boolean
)
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column

Base = declarative_base()

class SampleMixin(object):
    id = Column("Id", Integer, primary_key=True)
    name = Column("Name", String)
    description = Column("Description", String)
    is_active = Column("IsActive", Boolean)

class Sample(SampleMixin, Base):
    __tablename__ = 'Sample'
    __table_args__ = {'useexisting': True}

    def __init__(self, id, name, description, is_active):
        self.id = id
        self.name = name
        self.description = description
        self.is_active = is_active

    def __repr__(self):
        return "<(%d, '%s', '%s', %r)>" % (self.id, self.name,
                                self.description, self.isactive)

from sqlalchemy import select
print select([Sample.id, Sample.name])

-1
如果 zzzeek 提出的多重继承无法解决您的问题,请尝试将您的元类从 DeclarativeMeta 继承:
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta

Base = declarative_base()

class SampleMeta(DeclarativeMeta):
    #...

class Sample(Base):
    __metaclass__ = SampleMeta
    #...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接