Today, I accidentally came across a very interesting feature that was added in Django 5.1.
Developers have added the login_not_required decorator, which should be used in conjunction with django.contrib.auth.middleware.LoginRequiredMiddleware.
The appearance of this decorator intrigued me because redirection to pages after authentication doesn't work as well as I would like. Here, you get a ready-made functionality that makes automatic correct redirection and allows better control over user access areas on the site.
But there are also some problems with this solution.
Features of using login_not_required
Site behavior when LoginRequiredMiddleware is enabled
For minimal site setup to use login_not_required, you need to enable LoginRequiredMiddleware in your settings.py file.
MIDDLEWARE = [
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.LoginRequiredMiddleware'
]
And also mark the route with this decorator.
urlpatterns = [
path('login/', login_not_required(LoginView.as_view()), name='login')
]
In this case, an unauthenticated user will only be able to access the authentication page.
All other pages will be inaccessible to anonymous users.
Thus, the approach to site development changes completely. Now you need to open those pages to anonymous users that can be available to them.
This may add work. On the other hand, personally, I see it as a plus because by default all pages are inaccessible to anonymous users, and the developer will decide which pages to make publicly available.
Personally, I like this approach more.
Pages only for anonymous users
A decorator or another solution is still needed to allow access only for anonymous users. For example, a user registration page.
And here a custom solution is still required. For example, like this:
def anonymous_required(
function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None
):
actual_decorator = user_passes_test(
lambda u: not u.is_authenticated,
login_url=login_url,
redirect_field_name=redirect_field_name,
)
if function:
return actual_decorator(function)
return actual_decorator
And connecting urls.py
urlpatterns = [
path('register/', login_not_required(anonymous_required(RegisterView.as_view())), name='register')
]
login_not_required requires an additional solution for mass opening of routes on the site
This decorator cannot be applied to the path function, inside which the urls.py file is connected.
For example, using the django-decorator-include package.
Installation
pip install django-decorator-include
Usage
from decorator_include import decorator_include
urlpatterns = [
path('captcha/', decorator_include(login_not_required, 'captcha.urls')),
]
Conclusion
On the plus side, I can note gaining more control over user access.
It's much better to allow access as the site is developed than to prohibit it after incidents have already occurred.
On the downside, I would note the additional load and control when writing routes.
And also the need for additional solutions for specific situations using this decorator.

Comments
Nothing yet. Say the first thing.
Sign in to join the conversation.