2013-08-17 61 views
0

我有一个django模型需要做一些处理引用自定义用户模型。懒惰类属性修饰器

我无法在类加载时使用此模型的类,因为类的加载顺序未知。

所以我需要添加一些类属性在运行时,在我加入他们在__init____new__喜欢的时刻:

def __new__(cls, *args, **kwargs): 
    # hack to avoid INSTALLED_APPS initialization conflicts. 
    # get_user_model() can't be called from this module at class loading time, 
    # so some class attributes must be added later. 
    # Metaclasses could me more appropiate but I don't want to override 
    # dango's metaclasses. 
    if not hasattr(cls, '_reverse_field_name_to_user'): 
     cls._find_reverse_field_name_to_user() 
    return Group.__new__(cls, *args, **kwargs) 

它的工作原理,但看起来可怕,所以我想过使用的东西像@lazyclassproperty这些属性。

我发现了几个@classproperty@lazyproperty装饰器,但两个都没有,我也不知道如何自己写一个装饰器。

问题:我怎么能编码这样的装饰?或者建议另一种更清洁的替代方案来实现我目前愚蠢的实施。

回答

3

金字塔框架有一个非常漂亮的装饰叫做reify,但它仅适用于实例级别,你想一流水平,让我们稍作修改

class class_reify(object): 
    def __init__(self, wrapped): 
     self.wrapped = wrapped 
     try: 
      self.__doc__ = wrapped.__doc__ 
     except: # pragma: no cover 
      pass 

    # original sets the attributes on the instance 
    # def __get__(self, inst, objtype=None): 
    # if inst is None: 
    #  return self 
    # val = self.wrapped(inst) 
    # setattr(inst, self.wrapped.__name__, val) 
    # return val 

    # ignore the instance, and just set them on the class 
    # if called on a class, inst is None and objtype is the class 
    # if called on an instance, inst is the instance, and objtype 
    # the class 
    def __get__(self, inst, objtype=None): 
     # ask the value from the wrapped object, giving it 
     # our class 
     val = self.wrapped(objtype) 

     # and set the attribute directly to the class, thereby 
     # avoiding the descriptor to be called multiple times 
     setattr(objtype, self.wrapped.__name__, val) 

     # and return the calculated value 
     return val 

class Test(object): 
    @class_reify 
    def foo(cls): 
     print "foo called for class", cls 
     return 42 

print Test.foo 
print Test.foo 

运行的程序,并将它打印

foo called for class <class '__main__.Test'> 
42 
42 
+0

工程就像一个魅力。非常感谢,我希望我能不止一次地开心! –