2013-08-17 59 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

工程就像一個魅力。非常感謝,我希望我能不止一次地開心! –