How do I restrict access to admin pages in Django?

Overwrite the admin_view part of the AdminSite class before using it in the urls.

In admin.py file (create it if you don't have it) add:

from functools import update_wrapper

from django.http import Http404
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect


def admin_view(view, cacheable=False):
    """
    Overwrite the default admin view to return 404 for not logged in users.
    """
    def inner(request, *args, **kwargs):
        if not request.user.is_active and not request.user.is_staff:
            raise Http404()
        return view(request, *args, **kwargs)

    if not cacheable:
        inner = never_cache(inner)

    # We add csrf_protect here so this function can be used as a utility
    # function for any view, without having to repeat 'csrf_protect'.
    if not getattr(view, 'csrf_exempt', False):
        inner = csrf_protect(inner)

    return update_wrapper(inner, view)

and then in your urls file add:

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.defaults import page_not_found

from my_project.admin import admin_view
admin.site.admin_view = admin_view

urlpatterns = patterns('',
    url(r'^admin/login/', page_not_found),
    url(r'^admin/', include(admin.site.urls)),
)

Of course if you still want the login to be found then remove the url(r'^admin/login/', page_not_found) line.


I ended up writing a middleware for it:

from django.core.urlresolvers import reverse
from django.http import Http404

class RestrictStaffToAdminMiddleware(object):
    """
    A middleware that restricts staff members access to administration panels.
    """
    def process_request(self, request):
        if request.path.startswith(reverse('admin:index')):
            if request.user.is_authenticated():
                if not request.user.is_staff:
                    raise Http404
            else:
                raise Http404