Take the 2-minute tour ×

I have a declarative base class Entity which defines the column name as polymorphic, e.g.

class Entity(DeclarativeBase):
    name = Column('name', String(40))
    __mapper_args__ = {'polymorphic_on':name}

In subclasses, I could now say

class Experiment(Entity):
    __mapper_args__ = {'polymorphic_identity': "experiment"}

and be done. However, I would like to ease the creation of subclasses for the users of my library and therefore make the following possible:

  • Have a better syntax for it which is not as convoluted as the default syntax. This could be a simple assignment poly_id = "exp" inside the class or maybe a class decorator.
  • If no polymorphic_identity is given, extract the name from the name of the subclass.

I tried to get this done using metaclasses (only the second part):

from sqlalchemy.ext.declarative import DeclarativeMeta

class Meta(type):
    def __init__(cls, classname, bases, dict_):
        dict_["__mapper_args__"] = {'polymorphic_identity': classname}
        return super(Meta, cls).__init__(classname, bases, dict_)

class CombinedMeta(Meta, DeclarativeMeta):

class Experiment(Entity):
    __metaclass__ = CombinedMeta

so that, in my opinion, my Meta should set the name before calling the DeclarativeMeta but it does not seem to work. So either the DeclarativeMeta which supposedly sets the polymorphic name never sees the change because I messed up the MRO or what I’m doing is plain wrong anyway. What would I need to change or is there even something like this in SQLAlchemy already?

share|improve this question

2 Answers 2

up vote 6 down vote accepted

Shame on me but the problem could easily be solved by not using the dict_ but by setting the attribute directly on cls.

class Meta(DeclarativeMeta):
    def __init__(cls, *args, **kw):
        if getattr(cls, '_decl_class_registry', None) is None:
            return # they use this in the docs, so maybe its not a bad idea
        cls.__mapper_args__ = {'polymorphic_identity': cls.__name__}
        return super(Meta, cls).__init__(*args, **kw)

class Experiment(Entity):
    __metaclass__ = Meta
share|improve this answer

Recent sqlalchemy docs show ways of using mixin classes for such purposes (I'm not sure whether it only works in versions >= 0.6 or if it is only better documented now)


share|improve this answer
That does not really work in that form because it doesn’t allow me to dynamically set the __mapper_args__; it would just allow me to set a predefined __mapper_args__ in all classes the mixin is used in. –  Debilski Dec 16 '10 at 15:52

Your Answer


