# Restricting Views via LoginRequiredMixin and LoginRequiredMiddleware.

**URL:** <https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097>\
**Category:** Using Django\
**Created:** [December 18, 2021, 6:40pm UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097 "2021-12-18T18:40:35Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![rgd\_dev](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rgd_dev/32/6734_2.png) [@rgd\_dev](https://forum.djangoproject.com/u/rgd_dev)\
**Post date:** [December 18, 2021, 6:40pm UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097/1 "2021-12-18T18:40:35Z")

</div>

Hello there! I’d like to ask a few questions regarding restricting views.

Currently, most of my views look a bit like this:

```python
class ExampleView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    fields = ["field_a", "field_b", "field_c"]
    model = ExampleModel
    permission_required = ["examples.add_examplemodel"]
    success_url = reverse_lazy("examples:list")
    template_name = "examples/create.html"

```

I’m checking not only if a user is authenticated, but also if that user has permission to access a given resource.

Out of all my views, I think only 2 or 3 are “public views” ( **AnonymousUser** can access them).

With that said, I’ve been using **LoginRequiredMixin** and **PermissionRequiredMixin** because Django provides them out of the box and the documentation is pretty good ([Using the Django authentication system | Django documentation | Django](https://docs.djangoproject.com/en/3.2/topics/auth/default/#the-loginrequired-mixin)). Although I’ve never seen them being used that way (`class SomeView(LoginRequiredMixin, PermissionRequiredMixin, ...):`) in the docs or by 3rd party libs, I assume there’s nothing wrong with this approach. Both inherit from **AccessMixin** , so I guess it’s okay. Please correct me if I’m wrong.

I’d like to upgrade that set up to something more developer friendly by adding a middleware **LoginRequiredMiddleware** instead of adding **LoginRequiredMixin** to most of my views.

Can you guys give me some feedback on my current configuration (see below)?

- Does it look good? See any issues?
- Is there a better way to do this?
- LoginRequiredMixin vs. LoginRequiredMiddleware … any reason to prefer one over the other?
- Should I be using `if public_view in path:` instead of `if path.startswith(public_view):` ?
- Does the middleware order look good?
- Do you know of any reputable libraries that implement something similar?

```python
# settings.py

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "myapp.middleware.LoginRequiredMiddleware", # <<<==========
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

PUBLIC_VIEWS = [
    "app1:login",
    "app1:signup",
    "app2:landing",
]

```

```python
# middleware.py

class LoginRequiredMiddleware:
    def __init__ (self, get_response):
        self.get_response = get_response
        self.public_views = [reverse(view) for view in settings.PUBLIC_VIEWS]

    def __call__ (self, request):
        path = request.get_full_path()
        is_public_view = False
        for public_view in self.public_views:
            if path.startswith(public_view):
                is_public_view = True
                break
        if not is_public_view:
            if not request.user.is_authenticated:
                return redirect_to_login(path)
            if path.startswith(reverse("admin")) and not request.user.is_staff:
                raise PermissionDenied("Some message")
        return self.get_response(request)

```

Any feedback is appreciated. Thank you!

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [December 19, 2021, 12:45am UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097/2 "2021-12-19T00:45:16Z")

</div>

You don’t need both LoginRequired and PermissionsRequired. Unless you’ve done something really unusual, AnonymousUser is never going to be granted permissions so LoginRequired is redundant.

---

<div class="post-metadata">

**Author:** ![rgd\_dev](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rgd_dev/32/6734_2.png) [@rgd\_dev](https://forum.djangoproject.com/u/rgd_dev)\
**Post date:** [December 19, 2021, 1:52am UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097/3 "2021-12-19T01:52:25Z")

</div>

I see your point. So, if I need to restrict a view called **AnotherExampleView** in a way that any authenticated user can access it, I can do something like this:

```python
class AnotherExampleView(PermissionRequiredMixin, TemplateView):
    # ...
    permission_required = []

```

Right? I mean, **AnotherExampleView** only requires the user to be authenticated, but it does not require any kind of permission. I can just leave _permission\_required_ as an empty list and that’s that.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [December 19, 2021, 2:03am UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097/4 "2021-12-19T02:03:07Z")

</div>

No, for that you would use LoginRequiredMixin.

It’s that you never need to use _both_ LoginRequiredMixin _and_ PermissionRequiredMixin for the _same_ view.

---

<div class="post-metadata">

**Author:** ![rgd\_dev](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/rgd_dev/32/6734_2.png) [@rgd\_dev](https://forum.djangoproject.com/u/rgd_dev)\
**Post date:** [December 20, 2021, 1:46am UTC](https://forum.djangoproject.com/t/restricting-views-via-loginrequiredmixin-and-loginrequiredmiddleware/11097/5 "2021-12-20T01:46:46Z")

</div>

I see. Thank you so much for the help!
