3


I want to control that only the superuser and for example the teacher, can access a page inherited from UpdateView and redirect others to the /404 page.

My class in views.py :

class Edit_news(UpdateView):
    model = News
    form_class = edit_NewsForm
    template_name = "profile/Edit_news.html"

URL of class in urls.py :

from django.urls import path
from .views import Edit_news

urlpatterns = [
    path("edit-news/<pk>", Edit_news.as_view()),
]
  • Can you please mention "Edit_news.html" is the page that needs to be accessed only by superuser – Chandan Aug 24 '21 at 10:39

1 Answers1

1

Solution 1

You can override View.dispatch() which is the entrypoint of any HTTP methods to check first the user.

dispatch(request, *args, **kwargs)

The view part of the view – the method that accepts a request argument plus arguments, and returns a HTTP response.

The default implementation will inspect the HTTP method and attempt to delegate to a method that matches the HTTP method; a GET will be delegated to get(), a POST to post(), and so on.

class Edit_news(UpdateView):
    ...

    def dispatch(self, request, *args, **kwargs):
        if (
            request.user.is_superuser
            or request.user.has_perm('app.change_news')  # If ever you attach permissions to your users
            or request.user.email.endswith('@teachers.edu.org')  # If the email of teachers are identified by that suffix
            or custom_check_user(request.user)  # If you have a custom checker
        ):
            return super().dispatch(request, *args, **kwargs)
        return HttpResponseForbidden()

    ...

If you want it to be different for HTTP GET and HTTP POST and others, then override instead the specific method.

class django.views.generic.edit.BaseUpdateView

Methods

get(request, *args, **kwargs)

post(request, *args, **kwargs)

Related reference:

Solution 2

You can also try UserPassesTestMixin (the class-based implementation of user_passes_test).

class Edit_news(UserPassesTestMixin, UpdateView):  # Some mixins in django-auth is required to be in the leftmost position (though for this mixin, it isn't explicitly stated so probably it is fine if not).
    raise_exception = True  # To not redirect to the login url and just return 403. For the other settings, see https://docs.djangoproject.com/en/3.2/topics/auth/default/#django.contrib.auth.mixins.AccessMixin

    def test_func(self):
        return (
            self.request.user.is_superuser
            or self.request.user.has_perm('app.change_news')  # If ever you attach permissions to your users
            or self.request.user.email.endswith('@teachers.edu.org')  # If the email of teachers are identified by that suffix
            or custom_check_user(self.request.user)  # If you have a custom checker
        )

    ...