Check if a function has a decorator
Asked Answered
C

2

17

My question is a general one, but specifically my application is the login_required decorator for Django.

I'm curious if there is a way to check if a view/function has a specific decorator (in this case the login_required decorator)

I am redirecting after logging a user out, and I want to redirect to the main page if the page they are currently on has the login_required decorator. My searches have yielded no results so far.

Catchpole answered 30/3, 2011 at 17:9 Comment(0)
A
17

Build your own login_required decorator and have it mark the function as decorated--probably the best place to mark it would be in the func_dict.

from django.contrib.auth.decorators import login_required as django_l_r

# Here you're defining your own decorator called `login_required`
# it uses Django's built in `login_required` decorator
def login_required(func):
    decorated_func = django_l_r(func)
    decorated_func.func_dict['login_is_required'] = True
    return decorated_func

@login_required # Your decorator
def authenticatedd_view(request):
    pass

def unauthenticated_view(request):
    pass

Now you can check to see if a view was decorated like this...

# Assume `a_view` is view function
>>> a_view.func_dict.get('login_is_required',False)

If you're confused about Python decorators see this SO question/answer: How to make a chain of function decorators?

Anabiosis answered 30/3, 2011 at 17:36 Comment(6)
"mark the function as decorated"? Why not mark each function with the proper URL-name to redirect to on logout? That would be more directly useful.Sternick
@Sternick It sounds like you mean attaching either a URL or a URL-name to the view function, I believe that would be bad practice as it would be mixing your urls and views, which are expressly separated in Django.Anabiosis
@Chris W.: URL-names are referenced in views so that reverse() will work. Similarly, URL-names are reference in templates so that {% url %} will work. I'm not sure what you mean by "mixing". Can you explain further?Sternick
@Sternick now you have me confused, the whole point of reverse() and {% url %} is to convert a view function (or a string descriptor of a view function) into a url. This is so that neither your HTML templates nor your view functions themselves need to know anything about URLs.Anabiosis
@Chris W.: URL's can have names. docs.djangoproject.com/en/1.3/topics/http/urls/…. That can simplify locating a standard URL from a number of view functions. Providing a standard URL name for a logout is often very, very handy.Sternick
@Sternick ok, here is the disconnect, I see in the django docs for reverse that the input to reverse "is either the function name (either a function reference, or the string version of the name, if you used that form in urlpatterns) or the URL pattern name." I wasn't aware that you could use the URL pattern name.Anabiosis
C
2

It seems that your situation is as follows: 1. You have pages that are secured and behind a login-required decorator 2. You have pages that are non-secure and can be visited in both a logged-in state and anonymous state.

If I understand your requirements, you want a user to be redirected to Main Page (Assuming this to be the Welcome Page that can be visited in both a logged-in and Anonymous state) when a user logs out.

Why wouldn't you just limit the user's ability to logout from only secure pages, and then set your redirect_url on logout to the welcome screen?

Carmellacarmelle answered 30/3, 2011 at 18:18 Comment(2)
+1: That's what view functions are for. A logout view function can use if request.user.is_anonymous() to determine whether or not to log someone out, and which page to display.Sternick
Yes, but if you are trying to log them out and redirect them back to the page they logged out from, this does not work unless you can know if that page/view is protected with authentication.Catchpole

© 2022 - 2024 — McMap. All rights reserved.