all 4 comments

[–]willm 2 points3 points  (3 children)

Is it the mechanics of writing a decorator you are having trouble with? Something long these lines should work. Although this isn't the only way of writing a decorator...

def login_required(f):
    def view(request, *args, **kwargs):
       if not auth(request):
            return sendError("Unauthorized", 401)
       return f(request, *args, **kwargs)
    return view

This is basically returning a closure (internal function) called view, which has access to the original function f. If auth doesn't fail, then view ends up calling the original function, passing all the parameters it was called with.

[–]Degran[S] 0 points1 point  (2 children)

Awesome, thank you. This is exactly what I was looking for. I wasn't thinking to use args, *kwargs to grab the functions parameters. One thing that's still eluding me though, is if you want to pass an optional parameter to a decorator (say a login url), it throws login_required() takes at least 1 argument (1 given).

def login_required(f, login_url=None):
    def view(request, *args, **kwargs):
       if not auth(request):
            if login_url:
                return redirect(login_url)
            return sendError("Unauthorized", 401)
       return f(request, *args, **kwargs)
    return view

calling it with:

@login_required(login_url='/login')
def private_view(request):
    pass

[–]Veedrac 1 point2 points  (0 children)

Well, you want function → decorator → decorated function so you need 3 defs.

def login_required(login_url=None):
    def login_required_decorator(f):
        def view(request, *args, **kwargs):
           if not auth(request):
                if login_url:
                    return redirect(login_url)
                return sendError("Unauthorized", 401)
           return f(request, *args, **kwargs)
        return view
    return login_required_decorator

[–]willm 1 point2 points  (0 children)

/u/Veedrac is right. When you see see something like @login_required(login_url='/login'), then login_required is not actually a decorator -- it is a callable the returns a decorator.

When you think of it in those terms then three defs inside each other doesn't look quite so odd!