【问题标题】:How to define metaclass for a class that extends from sqlalchemy declarative base如何为从 sqlalchemy 声明性基础扩展的类定义元类
【发布时间】:2013-06-30 14:31:31
【问题描述】:

我使用: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)

我得到的错误是:

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)

它工作得很好。

我需要动态更新类的属性。所以,我将使用动态属性和列名。我需要上面的代码才能到达那里。

请帮忙

【问题讨论】:

    标签: python dynamic attributes sqlalchemy metaclass


    【解决方案1】:

    要使用元类,在这种情况下,它必须从声明式DeclaredMeta 派生。但是这个用例不需要元类。使用mixins:

    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])
    

    【讨论】:

      【解决方案2】:

      如果 zzzeek 提出的多重继承不能解决您的问题,请尝试从 DeclarativeMeta 继承您的 MetaClass:

      from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
      
      Base = declarative_base()
      
      class SampleMeta(DeclarativeMeta):
          #...
      
      class Sample(Base):
          __metaclass__ = SampleMeta
          #...
      

      【讨论】:

        猜你喜欢
        • 2016-09-27
        • 2014-05-06
        • 2015-02-25
        • 1970-01-01
        • 2013-07-24
        • 2017-02-12
        • 2012-11-03
        • 2015-07-09
        • 2010-10-22
        相关资源
        最近更新 更多