Yes, it is possible, but not terribly straightforward. The complicating factor is that Django's login_required
decorator actually passes through 2 levels of indirection (one dynamic function and one other decorator), to end up at django.contrib.auth.decorators._CheckLogin, which is a class with a __call__
method.
Let's say you have a non-django, garden-variety decorated function that looks like this:
def my_decorator(func):
def inner():
return func()
return inner
@my_decorator
def foo():
print foo.func_name
# results in: inner
Checking to see if the function foo
has been wrapped can be as simple as checking the function object's name. You can do this inside the function. The name will actually be the name of the last wrapper function. For more complicated cases, you can use the inspect
module to walk up the outer frames from the current frame if you're looking for something in particular.
In the case of Django, however, the fact that the decorator is actually an instance of the _CheckLogin
class means that the function is not really a function, and therefore has no func_name
property: trying the above code will raise an Exception.
Looking at the source code for django.contrib.auth.decorators._CheckLogin
, however, shows that the _CheckLogin
instance will have a login_url
property. This is a pretty straightforward thing to test for:
@login_required
def my_view(request):
is_private = hasattr(my_view, 'login_url')
Because _CheckLogin
is also used to implement the other auth decorators, this approach will also work for permission_required
, etc. I've never actually had a need to use this, however, so I really can't comment on what you should look for if you have multiple decorators around a single view... an exercise left to the reader, I guess (inspect the frame stack?).
As unrequested editorial advice, however, I would say checking the function itself to see if it was wrapped like this strikes me as a bit fiddly. You can probably imagine all sorts of unpredictable behaviour waiting to happen when a new developer comes to the project as slaps on some other decorator. In fact, you're also exposed to changes in the django framework itself... a security risk waiting to happen.
I would recommend Van Gale's approach for that reason as something that is explicit, and therefore a much more robust implementation.