2013-07-03 17 views
8

używać: Python 2.6 i SQLAlchemy 0.6.1Jak zdefiniować metaklasa dla klasy, która rozciąga się od sqlalchemy deklaratywnej bazy

To, co próbuję zrobić:

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) 

i błąd I Dostaję to:

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 

teraz, jeśli zrobić to samo powyżej używając

class Sample(object) 

zamiast

class Sample(Base) 

działa absolutnie w porządku.

Muszę dynamicznie aktualizować atrybuty klasy. Tak więc będę używał dynamicznych atrybutów i nazw kolumn. I potrzebuję powyższego kodu do pracy, aby móc się tam dostać.

Proszę o pomoc

Odpowiedz

8

używać metaklasą, musiałaby pochodzić z Declaratives DeclaredMeta w tym przypadku. Ale w przypadku tego przypadku nie jest potrzebna metaklasa. Użyj 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]) 
+0

Wielokrotne dziedziczenie .... Genius .... Jak oczekiwano od twórcy sqlalchemy użytkownika. – goFrendiAsgard

-1

Jeżeli proponowane przez zzzeek wielokrotnego dziedziczenia nie może rozwiązać Twój problem spróbuj odziedziczyć swoją metaklasa z DeclarativeMeta:

from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta 

Base = declarative_base() 

class SampleMeta(DeclarativeMeta): 
    #... 

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