0

我有很多类是我的数据库模式多态性的一部分。对于他们中的大多数,我(需要)做:

__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

4 回答 4

2

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

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

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

class SomeOtherTable(Base, PolyMixin):
    __tablename__ = "something_else"
于 2013-02-27T00:34:10.807 回答
1

您的装饰器不起作用,因为它在构建类后尝试修改类,并且此时映射器已经设置。

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

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

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

于 2013-02-27T02:08:11.423 回答
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

(很遗憾)

于 2013-02-28T11:06:29.133 回答
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,或者有一个外部字典将类名映射到值,或者甚至创建一个虚构的“基础”来记住这个值,这样你就可以编写

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

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

于 2015-07-18T14:19:01.330 回答