Question

Background & attempted code:

I'm using Django 1.6.2 (on Python 3.3) and would like all views to effectively have the login_required decorator applied to them and re-use the actual admin login form. Note that the admin app will also be in use with the default urls. I have looked at Redirect to admin for login and the resolution of that is what I'd like to avoid.

A popular route appears to be using custom middleware as demonstrated by the Login Required Middleware with Next Parameter DjangoSnippet. I've adapted this snippet and am using it as following:

project_name.middleware:

from django.contrib.auth.views import redirect_to_login

class LoginRequired:
    def process_request(self, request):
        if request.user.is_authenticated():
            return
        if request.path != '/admin/login/':
            return redirect_to_login(request.path, '/admin/login/')

settings.py:

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',    
    'project_name.middleware.LoginRequired', # <----------
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

Issue

This almost works, except the ?next= provided to /admin/login is not handled quite as I'd expect it to be. Given a request of http://localhost:8000/admin/login/?next=/ (which successfully displays the admin login form and enables logging in), upon submittal of correct information, I get a 404 response and a The requested admin page does not exist. which possibly implies the login form is treating the provided query parameter as relative to something.

Question

What could I do to get this to work as expected?

Note: I wouldn't be massively surprised if this is a wild goose chase, so if this isn't possible then I'm open to answers to that effect (but it would good if they included citations/references so I can fill a gap in my understanding here).

Was it helpful?

Solution

Not yet available

admin.site.urls have been provided with a login endpoint only very recently which explains the 404 you've experienced : django does not try to resolve it until you've successfully logged in.

Workaround

One first solution would be to create the endpoint, prepending your url.py with a new url(r'^admin/login/', admin.site.login, name='login'), route.

But that's not enough, the very same changeset referenced earlier introduces the use of a redirection parameter. Before that, it's forced to request.get_full_path() in the login view of admin. Therefore, it will not redirect, but loop on the login page.

Workaround 2 - contrib.auth

The trick to make it all work would be to bypass admin and use auth's login view directly, borrowing only admin's template.

from django.contrib import auth
#...
url(r'^admin/login/', auth.views.login, kwargs={"template_name":"admin/login.html"}, name='login'),

With this route, you should get what you want.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top