Hello,

I tried to implement the table_per_related.py solution in my code but I 
face new problems related to metaclasses.

Here is a schema to help you to understand the code :

<https://lh3.googleusercontent.com/-NesWeuhrl1M/Whl4BN4xHMI/AAAAAAAAAPU/tU_Pd_T03cwsWHtamsb8GY7PjkLgotScwCLcBGAs/s1600/schema_animals%2526cars.png>


My animal and car classes have to be inherited from a generic class called 
"Stockable" which use a metaclass called "MetaBase". In addition to this, 
my classes Animal and Car must also be inherited from the Base class of 
SQLAlchemy.

Now, I would like to be able to do this kind of things in order to map the 
"Description" attribute of these classes :

class Animal(Stockable, Base, metaclass=DeclDescription)

or

class Animal(Stockable, Base, HasDescription)

I tried several things but until now, impossible to make all these classes 
work together...

Here is the code :

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import as_declarative, declared_attr
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship


class MetaBase(type):


    def __init__(cls, nom, bases, contenu):
        type.__init__(cls, nom, bases, contenu)
        print("GenericMetaClass - __init__")


class DeclMetaBase(MetaBase, DeclarativeMeta):


    def __init__(cls, nom, bases, contenu):
        MetaBase.__init__(cls, nom, bases, contenu) 
        DeclarativeMeta.__init__(cls, nom, bases, contenu)


@as_declarative()
class Base(metaclass=DeclMetaBase):
    """Base class which provides automated table name
    and surrogate primary key column.


    """
    @declared_attr
    def __tablename__(cls):
        return cls.__name__.lower()
    id = Column(Integer, primary_key=True)


class Stockable(metaclass=MetaBase):


    def __init__(self):
        print("Stockable - __init__")


class Description(Stockable):


    name = Column(String)


    def __init__(self, name):
        self.name = name
        self.parent = None


    def __repr__(self):
        return self.name


class HasDescription(object):


    @declared_attr
    def descriptions(cls):
        cls.Description = type(
            "%sDescription" % cls.__name__,
            (Description, Base,),
            dict(
                __tablename__="%s_descriptions" %
                            cls.__tablename__,
                parent_id=Column(Integer,
                            ForeignKey("%s.id" % cls.__tablename__)),
                parent=relationship(cls)
            )
        )
        return relationship(cls.Description)


class DeclDescription(DeclMetaBase, HasDescription):


    def __init__(cls, nom, bases, contenu):
        DeclMetaBase.__init__(cls, nom, bases, contenu) 


class Animal(Stockable, Base, metaclass=DeclDescription):


    tablename = "animals"
    id = Column(Integer, primary_key=True)
    name = Column(String)


    def __init__(self, name):
         self.name = name


    def __repr__(self):
        return self.name


class Car(Stockable, Base, metaclass=DeclDescription):


    tablename = "cars"
    id = Column(Integer, primary_key=True)
    name = Column(String)


    def __init__(self, name):
        self.name = name


    def __repr__(self):
        return self.name


engine = create_engine('sqlite://', echo=True)


Base.metadata.create_all(engine)


Session = sessionmaker(bind=engine)
session = Session()


rex = Animal("Rex")
swift = Car("Suzuki Swift")


d1 = Description("Rex is a good dog.")
d2 = Description("What a beautiful car !")


rex.description = d1
d1.parent = rex
swift.description = d2
d2.parent = swift


session.add(rex)
session.add(swift)


session.commit()


And the error :

Traceback (most recent call last):
  File "C:\Users\user\Desktop\sa_tests\Generic Associations\description.py", 
line 21, in <module>
    class Base(metaclass=DeclMetaBase):
  File "C:\Users\user\Desktop\sa_tests\Generic Associations\description.py", 
line 18, in _init_
    DeclarativeMeta.__init__(cls, nom, bases, contenu)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\api.py", 
line 64, in _init_
    as_declarative(cls, classname, cls.__dict_)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 88, in _as_declarative
    MapperConfig.setup_mapping(cls, classname, dict)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 103, in setup_mapping
    cfg_cls(cls, classname, dict)
  File "C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\base.py", 
line 125, in _init_
    clsregistry.add_class(self.classname, self.cls)
  File 
"C:\Python34\lib\site-packages\sqlalchemy\ext\declarative\clsregistry.py", 
line 34, in add_class
    if classname in cls._decl_class_registry:
AttributeError: type object 'Base' has no attribute '_decl_class_registry'


Does someone have an idea ?

Thank you !

Olaf

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to