Skip to content Skip to sidebar Skip to footer

Sqlalchemy Class Decoration For __mapper_args__

I have a lot of classes which are part of polymorphism with my DB schema. With most of them I (need to) do: __mapper_args__ = {'polymorphic_identity': unique_integer} # unique_inte

Solution 1:

Use a mixin. Normally they're kind of a nightmare, but injecting common state into a declarative class seems like a reasonable use.

classPolyMixin(object):
    __mapper_args__ = {'polymorphic_identity': 10}

classSomeTable(Base, PolyMixin):
    __tablename__ = "something"classSomeOtherTable(Base, PolyMixin):
    __tablename__ = "something_else"

Solution 2:

Your decorator doesn't work because it tries to modify the class after it's been constructed, and at that point the mapper has already been set up.

defpolid(value):
    returntype("mixinclass", (object,), {"__mapper_args__": {'polymorphic_identity': value}})

classClassName(polid(10), Inherited):
    pass

This creates a brand new class every time polid is called, with whatever custom mapper args you require.

Solution 3:

Perhaps a bit better, less magical solution attained so far could be:

defPID(value):
    ''' Mixin Class Generator For Polymorphic Identity Inheritance '''classMixinClassForPolymorphicIdentityInheritance: 
        __mapper_args__ = {'polymorphic_identity': value}
    return MixinClassForPolymorphicIdentityInheritance

Usage:

classInheritingClass(PID(pidv), Parent): pass

(unfortunately)

Solution 4:

What exactly is wrong with metaclass approach?

classPolyMeta(DeclarativeMeta):
    def__new__(cls, clsname, bases, namespace, value=None, **kwargs):
        if value isnotNone:
            namespace['__mapper_args__'] = dict(polymorphic_identity=value)
        returnsuper().__new__(cls, clsname, bases, namespace, **kwargs)

classInherited(Base, metaclass=PolyMeta): ...

classClassName(Inherited, value=10): ...

Of course, in Py2 you'll have to find some other way to signal information to the metaclass, but that's the price to pay for using a legacy language. :-P It shouldn't be so hard though: use a special attribute _value, or have an external dict mapping class names to values, or even make a fictional "base" remembering the value so you could write

class ClassName(Inherited, Value(10)): ...

In fact, I think that last approach is the best (if you're still stuck on Py2). If you need help with it, ask and I'll try to write it out.

Post a Comment for "Sqlalchemy Class Decoration For __mapper_args__"