__mapper_args__的SQLAlchemy类装饰

时间:2013-02-27 00:24:33

标签: python python-2.7 sqlalchemy polymorphism

我有很多类,它们是我的数据库模式的多态性的一部分。 其中大部分我都需要做:

__mapper_args__ = {'polymorphic_identity': unique_integer}
# unique_integer is a unique integer different for each class ex: 10

而不是这个,我想使用装饰器,即:

@polid(10)
class ClassName(Inherited):
    # instead of repeating for each class the following:
    # __mapper_args__ = {'polymorphic_identity': 10}
    # I would like to have above decorator or something to do the trick.
    pass

我该怎么做?我需要使用什么样的装饰器?以下不起作用(不注册):

def polid(v):
    def x(f):
        f.__mapper_args__ = {'polymorphic_identity': v}
        return f
    return x

4 个答案:

答案 0 :(得分:2)

使用mixin。通常它们是一种噩梦,但将共同状态注入声明性类似乎是合理的用法。

class PolyMixin(object):
    __mapper_args__ = {'polymorphic_identity': 10}

class SomeTable(Base, PolyMixin):
    __tablename__ = "something"

class SomeOtherTable(Base, PolyMixin):
    __tablename__ = "something_else"

答案 1 :(得分:1)

你的装饰器不起作用,因为它在构造之后试图修改类,并且此时已经设置了映射器。

def polid(value):
    return type("mixinclass", (object,), {"__mapper_args__": {'polymorphic_identity': value}})

class ClassName(polid(10), Inherited):
    pass

每次调用polid时都会创建一个全新的类,使用您需要的任何自定义映射器args。

答案 2 :(得分:1)

到目前为止,可能会更好,更不神奇的解决方案可能是:

def PID(value):
    ''' Mixin Class Generator For Polymorphic Identity Inheritance '''
    class MixinClassForPolymorphicIdentityInheritance: 
        __mapper_args__ = {'polymorphic_identity': value}
    return MixinClassForPolymorphicIdentityInheritance

用法:

class InheritingClass(PID(pidv), Parent): pass

(不幸的是)

答案 3 :(得分:0)

元类方法究竟出了什么问题?

class PolyMeta(DeclarativeMeta):
    def __new__(cls, clsname, bases, namespace, value=None, **kwargs):
        if value is not None:
            namespace['__mapper_args__'] = dict(polymorphic_identity=value)
        return super().__new__(cls, clsname, bases, namespace, **kwargs)

class Inherited(Base, metaclass=PolyMeta): ...

class ClassName(Inherited, value=10): ...

当然,在Py2中,您必须找到一些其他方式向元类信号发送信号,但这是使用传统语言的代价。 :-P它应该不是那么难:使用一个特殊的属性_value,或者有一个外部dict将类名称映射到值,甚至可以创建一个虚构的“基础”来记住这个值,这样你就可以写了

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

事实上,我认为最后一种方法是最好的(如果你仍然坚持Py2)。如果您需要帮助,请询问,我会尝试写出来。