我想做类似于此的事情,这可以理解为导致SyntaxError:
@api_view(['GET'])
if settings.USE_API_KEY:
@authentication_classes((TokenAuthentication, ))
@permission_classes((IsAuthenticated, ))
def all_announcements(request):
announcements = Announcement.objects.all()
serializer = AnnouncementSerializer(announcements, many=True)
return Response(serializer.data)
我如何实现类似的东西?
答案 0 :(得分:9)
我不会为此编写装饰器 - 请注意,装饰器语法允许返回装饰器的函数调用(实际上,这是decorators-with-parameters实际上做的)。所以:
def maybe_decorate(condition, decorator):
return decorator if condition else lambda x: x
@api_view(['GET'])
@maybe_decorate(settings.USE_API_KEY, authentication_classes((TokenAuthentication, )))
@maybe_decorate(settings.USE_API_KEY, permission_classes((IsAuthenticated, )))
def all_announcements(request):
...
答案 1 :(得分:6)
当您使用这样的装饰器时:
@decorator
def f():
...
它等同于:
def f():
...
f = decorator(f)
考虑到这一点,你可以像这样完成你想要的东西:
def all_announcements(request):
announcements = Announcement.objects.all()
serializer = AnnouncementSerializer(announcements, many=True)
return Response(serializer.data)
if settings.USE_API_KEY:
all_announcements = permission_classes((IsAuthenticated,))(all_announcements)
all_announcements = authentication_classes((TokenAuthentication,))(all_announcements)
all_announcements = api_view(['GET'])(all_announcements)
答案 2 :(得分:3)
这样做:
def my_decorator(condition):
def wrap(fn):
def new_f(*args,**kwargs):
# some code that uses the function fn (fn holds a reference to the function you have decorated)
pass
if condition:
return new_f
else:
return fn
return wrap
@my_decorator(settings.USE_API_KEY)
def all_announcements(request):
...
(显然是一个一般的例子,你需要申请你的特定代码,其中很多你没有包含在你的问题中,所以我不能提供一个完整的例子供你复制粘贴!)
您可以将此视为my_decorator(condition)
函数,返回一个新的装饰器wrap
,然后装饰您的函数。装饰器wrap
将使用条件来决定是否用new_f替换你的函数。
答案 3 :(得分:1)
这样的事情:
def my_conditional_wrapper(f):
if not condition():
return f
def wrapper(*args, **kwargs):
#wrap function here
pass
return wrapper
答案 4 :(得分:0)
如何?
def timeit(method):
def timed(*args, **kw):
if 'usetimer' not in kw:
return method(*args, **kw)
elif ('usetimer' in kw and kw.get('usetimer') is None):
return method(*args, **kw)
else:
import time
ts = time.time()
result = method(*args, **kw)
te = time.time()
if 'log_time' in kw:
name = kw.get('log_name', method.__name__.upper())
kw['log_time'][name] = int((te - ts) * 1000)
else:
print '%r took %2.2f ms' % \
(method.__name__, (te - ts) * 1000)
return result
return timed
def some_func(arg1, **kwargs):
#do something here
some_func(param1, **{'usetimer': args.usetimer})