I'd like the login form (AuthenticationForm from django.contrib.auth) to appear on every page in my site if the user is not logged in. When the user logs in, they will be redirected to the same page. If there is an error, the error will be shown on the same page with the form.
I suppose you'd need a context processor to provide the form to every template. But, then you'd also need every view to handle the posted form? Does this mean you need to create some middleware? I'm a bit lost.
Is there an accepted way of doing this?
Ok, I eventually found a way of doing this, although I'm sure there are better ways. I created a new middleware class called LoginFormMiddleware. In the process_request method, handle the form more or less the way the auth login view does:
class LoginFormMiddleware(object):
def process_request(self, request):
# if the top login form has been posted
if request.method == 'POST' and 'is_top_login_form' in request.POST:
# validate the form
form = AuthenticationForm(data=request.POST)
if form.is_valid():
# log the user in
from django.contrib.auth import login
login(request, form.get_user())
# if this is the logout page, then redirect to /
# so we don't get logged out just after logging in
if '/account/logout/' in request.get_full_path():
return HttpResponseRedirect('/')
else:
form = AuthenticationForm(request)
# attach the form to the request so it can be accessed within the templates
request.login_form = form
Now if you have the request context processor installed, you can access the form with:
{{ request.login_form }}
Note that a hidden field 'is_top_login_form' was added to the form so I could distinguish it from other posted forms on the page. Also, the form action is "." instead of the auth login view.