Django: Tweaking @login_required decorator
Solution 1
Write your own decorator - it's fairly straight forward. In fact, if you look at the Django source for login_required
, you should be able to fiddle around with a copy for your own purposes.
def my_login_required(function):
def wrapper(request, *args, **kw):
user=request.user
if not (user.id and request.session.get('code_success')):
return HttpResponseRedirect('/splash/')
else:
return function(request, *args, **kw)
return wrapper
Solution 2
I would recommend using a middleware instead. That will make it easier to drop once you move out of your private beta. There are a couple examples of login required middlewares on djangonsippets:
http://djangosnippets.org/snippets/1220/
http://djangosnippets.org/snippets/136/
I would recommend taking one of those and tweaking it to include you beta code logic.
Solution 3
HOW to re-use (tweak) internal Django login_required
For example, you need to allow access to page for only users who passed login_required checks and also are Coaches - and (save) pass coach instance to you view for further processing
decorators.py
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from profiles.models import CoachProfile
def coach_required(function):
def wrapper(request, *args, **kwargs):
decorated_view_func = login_required(request)
if not decorated_view_func.user.is_authenticated():
return decorated_view_func(request) # return redirect to signin
coach = CoachProfile.get_by_email(request.user.email)
if not coach: # if not coach redirect to home page
return HttpResponseRedirect(reverse('home', args=(), kwargs={}))
else:
return function(request, *args, coach=coach, **kwargs)
wrapper.__doc__ = function.__doc__
wrapper.__name__ = function.__name__
return wrapper
views.py
@coach_required
def view_master_schedule(request, coach):
"""coach param is passed from decorator"""
context = {'schedule': coach.schedule()}
return render(request, 'template.html', context)
Related videos on Youtube
Ben
Updated on September 02, 2020Comments
-
Ben almost 4 years
I want to begin a private Beta for my website. I have a splash page where a user can enter a code to then access the rest of the site. Currently, all the other site pages (except the splash page) consist of a series of redirects set up by requiring user login (via @login_required decorator).
I want both logged in users and people who enter the Beta Tester code to be able to access the rest of the site. That means that I can't just use the decorator for all my views.
Should I alter the @login_required decorator itself? I'm more tempted to just do the following (I added a session variable if user enters correct code on splash page).
def view_name(request): user=request.user if not user.id or not request.session.get('code_success'): return HttpResponseRedirect('/splash/')
Does this seem reasonable? I'd hate to have to repeat it for all my views
Brendan
-
Ben about 13 yearsHi Mark, that makes sense. I haven't fiddled around with using the non-standard middleware yet. The RequireLoginMiddleWare is cool and definitely would have saved me some time. I'm going to try these both out. Thanks!
-
Ben about 13 yearsRight, but I also want the guest user to be able to register a full account. Normally, I redirect from register page for logged in users. I guess that I can allow logged in users to register and this would work. I don't see a problem with this, right?
-
Ben about 13 yearsHi Steve, this seems like a good solution. I tried it out. First, I got an traceback telling me that renderer() was taking an argument. I then tried to add optional args/kwargs (renderer(*args, *kwargs)) and I got a practically indecipherable traceback that claimed there were MiddleWare errors. I then stripped renderer() from the overall function defintion, leaving just wrapper. That worked, though it's not recognizing request.session.get('code_success')
-
Ben about 13 yearsThe problem here is that I have logic in other parts of my application that depend on the {{user.is_authenticated}} context variable. I don't want beta guests to be able to have perm to certain things. I'd then have to add a permission layer on top of this methodology.
-
mif about 13 yearsI see. Maybe you can modify the register page to check for logged-in guest users. If you detect a guest account, show them a message that suggests to register for a full account or continue as guests.
-
Steve Mayne about 13 yearsI've edited the solution (for others who see it) - does it look correct now?
-
Ben about 13 yearsyeah it works now, Steve. I have one question, though. When I look at other decorators, I often see this ////return wraps(func)(wrapper)///. It doesn't seem like it the wraps function would be relevant here, but I've seen a similar tutorial where it's used. What's the story there?
-
Steve Mayne about 13 yearsI'm not sure I've seen cases where that's done - do you have an example?
-
Marshall almost 8 yearsLink to Django source: docs.djangoproject.com/en/dev/_modules/django/contrib/auth/…