Django staff login to all urls

Question:

I want to define some specific urls starts with /staff/* to access only by staff. So only staffs can access the urls starts with /staff/*

How can I define that in Django ?

Asked By: Karesh A

||

Answers:

Use a custom middleware. If the url starts with /staff/ and request.user is not staff, raise Http404 or return some special message to client.

Below is an example:

For django version < 1.10:

class StaffCheckMiddleware(object):
    def process_request(self, request):
        full_path = request.get_full_path()
        if full_path.startswith('/staff/') and not request.user.is_staff:
            raise Http404      

For django version 1.10 or above:

class StaffCheckMiddleware(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        full_path = request.get_full_path()
        if full_path.startswith('/staff/') and not request.user.is_staff:
            raise Http404

        response = self.get_response(request)
        return response

Then add StaffCheckMiddleware in settings.py.

Answered By: Han He

You can use user_passes_test or staff_member_required decorator for the view that you associate with your url (that starts with /staff/), an example might be as follows:

With user_passes_test decorator:

from django.contrib.auth.decorators import user_passes_test

@user_passes_test(lambda u: u.is_staff, login_url='/some_url/')
def your_view(request, ...):
    # Only for staff

With staff_member_required decorator:

from django.contrib.admin.views.decorators import staff_member_required

@staff_member_required
def your_view(request, ...):
    # Only for staff
Answered By: ettanany

For class-based views I just took the LoginRequiredMixin in django source code and created a new mixin using this base:

website/utils/is_staff_mixin.py

from django.contrib.auth.mixins import AccessMixin
from django.utils.translation import gettext_lazy as _
from django.contrib import messages
from django.shortcuts import redirect


class IsStaffMixin(AccessMixin):
    """Verify that the current user has staff status."""
    def handle_no_permission(self, request):
        messages.add_message(request, messages.ERROR, _("You need higher permissions in order to access this page."))
        return redirect("index")


    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            messages.add_message(request, messages.ERROR, _("You need to be logged in in order to access this page."))
            return redirect("login")
        if not request.user.is_staff:
            return self.handle_no_permission(request)
        return super().dispatch(request, *args, **kwargs)

If the user is not logged in, I redirect to the login page. If the user is logged in but don’t have the is_staff var set to True, I redirect to my homepage.

Here’s a real world example:

website/apps/gallery/views.py

from website.utils.is_staff_mixin import IsStaffMixin
from django.views.generic import DetailView, ListView

from .models import Gallery


class ListGalleriesView(IsStaffMixin, ListView):
    model = Gallery
    paginate_by = 5
    context_object_name = "galleries"
    queryset = Gallery.objects.all().order_by("-date_added")


class GalleryView(IsStaffMixin, DetailView):
    model = Gallery
    context_object_name = "gallery"
Answered By: sodimel