2009-12-04 5 views
1

매우 간단한 작업을 수행하고 잘 작동하는 템플릿 필터가 있지만 여기에 데코레이터를 사용하고 싶습니다. 데코레이터장고 템플릿 필터 데코레이터?

@register.filter(name="has_network") 
def has_network(profile, network): 
    hasnetworkfunc = getattr(profile, "has_%s" % network) 
    return hasnetworkfunc() 

이 (작동하지 않습니다) : 여기

@register.filter(name="has_network") 
@cache_function(30) 
def has_network(profile, network): 
    hasnetworkfunc = getattr(profile, "has_%s" % network) 
    return hasnetworkfunc() 

불행하게도 장식은 이해가되지 않습니다 불쾌한 장고 오류 ... 작동

코드의 원인 오류입니다 :

TemplateSyntaxError at /

Caught an exception while rendering: pop from empty list

데코레이터 내부에 중단 점을 설정하려고했는데 합리적인 이유가 있습니다. 그것도라고하지 않을 것을 확신 Y ...

하지만 단지의 경우 여기

내가 모의 장식으로 장식을 (일시적으로) 대체 (I 누군가가 묻습니다 알고) 데코레이터이다 그 아무것도하지 않는,하지만 난 아직 확인했다 같은 오류

def cache_function(cache_timeout): 
    def wrapper(fn): 
     def decorator(*args, **kwargs): 
      return fn(*args, **kwargs) 
     return decorator 
    return wrapper 

편집 를 얻을 수 : 데코레이터가 *args**kwargs 필요하기 때문에이 발생? 나는 적어도 하나의 arg를 취하는 필터를 보장하기 위해 pop()이 호출되고 있다고 가정한다.

이 문제 해결에 장식을 변경 :

def cache_function(cache_timeout): 
    def wrapper(fn): 
     def decorator(arg1, arg2): 
      return fn(arg1, arg2) 
     return decorator 
    return wrapper 

그러나 불행하게도이 장식의 일반적인 특성 유적 : 지금 무엇을 /를?

답변

0

최종 답변 : 더 우아한 뭔가가있을 수 있습니다

장식되고 있는지를 나타내는 장식에 추가 인수를 추가,하지만이 작동합니다.

from django.core.cache import cache 
from django.db.models.query import QuerySet 
try: 
    from cPickle import dumps 
except: 
    from pickle import dumps 
from hashlib import sha1 

cache_miss = object() 

class CantPickleAQuerySet(Exception): pass 

def cache_function(cache_timeout, func_type='generic'): 
    def wrapper(fn): 
     def decorator(*args, **kwargs): 
      try: 
       cache_indentifiers = "%s%s%s%s" % (
             fn.__module__, 
             fn.__name__, 
             dumps(args), 
             dumps(kwargs) 
             ) 
      except Exception, e: 
       print "Error: %s\nFailed to generate cache key: %s%s" % (e, fn.__module__, fn.__name__) 
       return fn(*args, **kwargs) 

      cache_key = sha1(cache_indentifiers).hexdigest() 

      value = cache.get(cache_key, cache_miss) 

      if value is cache_miss: 
       value = fn(*args, **kwargs) 

       if isinstance(value, QuerySet): 
        raise CantPickleAQuerySet("You can't cache a queryset. But you CAN cache a list! just convert your Queryset (the value you were returning) to a list like so `return list(queryset)`") 

       try: 
        cache.set(cache_key, value, cache_timeout) 
       except Exception, e: 
        print "Error: %s\nFailed to cache: %s\nvalue: %s" % (e, cache_indentifiers, value) 

      return value 

     no_arg2 = object() 
     def filter_decorator(arg1, arg2=no_arg2): 
      if arg2 is no_arg2: 
       return decorator(arg1) 
      else: 
       return decorator(arg1, arg2) 

     if func_type == 'generic': 
      return decorator 

     elif func_type == 'filter': 
      return filter_decorator 

    return wrapper