Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Decorate a function if condition is True?

I want to do something akin to this, which (understandably) results in a 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)

How can I implement something similiar to this?

like image 369
Marco Petersen Avatar asked Nov 27 '22 21:11

Marco Petersen


2 Answers

I would not write a decorator for this - rather note that the decorator syntax allows a function call that returns a decorator (and indeed, this is what decorators-with-parameters actually do). So:

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):
    ...
like image 71
Steve Jessop Avatar answered Dec 06 '22 16:12

Steve Jessop


When you use a decorator like this:

@decorator
def f():
    ...

It's equivalent to this:

def f():
    ...
f = decorator(f)

With that in mind, you could accomplish what you want like this:

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)
like image 33
Ismail Badawi Avatar answered Dec 06 '22 16:12

Ismail Badawi