17👍
There’s not any obvious way. The only thing that springs to mind is to write your own version of the decorator that puts a message into the session before redirecting, then get the login template to display the message from the session.
You’d need to use the code in django.contrib.auth.decorators
, in particular the user_passes_test
function – the bit to add the message would have to go before return HttpResponseRedirect
.
26👍
It took me a while to figure out a nice way of doing this, but I think I have an implementation, based on the answer of Daniel Roseman
First thing I did was creating a decorator that sets messages when a user is not logged in, exactly like login_required.
So I wrote login_required_message:
try:
from functools import wraps
except ImportError:
from django.utils.functional import wraps # Python 2.4 fallback.
from django.utils.decorators import available_attrs
from django.contrib import messages
default_message = "Please log in, in order to see the requested page."
def user_passes_test(test_func, message=default_message):
"""
Decorator for views that checks that the user passes the given test,
setting a message in case of no success. The test should be a callable
that takes the user object and returns True if the user passes.
"""
def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if not test_func(request.user):
messages.error(request, message)
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator
def login_required_message(function=None, message=default_message):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated, #fixed by removing ()
message=message,
)
if function:
return actual_decorator(function)
return actual_decorator
With this implementation you can now annotate your view methods like this:
from decorators import login_required_message
from django.contrib.auth.decorators import login_required
@login_required_message(message="You should be logged in, in order to see the index!")
@login_required
def index(request):
pass
Now first the message will be set, then the redirect will be performed.
However I actually don’t want to add the login_required_message decorator everywhere. It would be much nicer to have only one decorator. So lets chain them (simply add this to your decorator.py file after login_required_message):
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.decorators import login_required
def login_required_message_and_redirect(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None, message=default_message):
if function:
return login_required_message(
login_required(function, redirect_field_name, login_url),
message
)
return lambda deferred_function: login_required_message_and_redirect(deferred_function, redirect_field_name, login_url, message)
It took me a while to figure out this last line; but lambda’s to the rescue!
Now you can replace the two decorators with only login_required_message_and_redirect: Almost there! Since actually I want to use this new login_required_message-method everywhere, I add a monkey-patch for login_required and it is used everywhere (again add to the bottom of the decorators.py file)!
from django.contrib.auth import decorators
setattr(decorators, 'login_required', login_required_message_and_redirect)
which allows me to call:
# a message will appear, since login_required is monkey patched
@login_required
def logout(request):
pass
# or customize the message per view
@login_required(message="You should be logged in message! Available after monkey patch")
def index(request):
pass
- [Django]-Ignoring Django Migrations in pyproject.toml file for Black formatter
- [Django]-Django return redirect() with parameters
- [Django]-RequestDataTooBig Request body exceeded settings.DATA_UPLOAD_MAX_MEMORY_SIZE
2👍
This is an old question but I still have it 10 years later. Here is the solution I came up with. It’s kind of hacky but it’s only 7 lines of code including the decorator. You use 2 functions.
The first is mapped to the URL path. It checks to see if the user is logged in. If the user is not logged in, it sets a message. Regardless of the user’s login state, it returns with a call to the second function.
The second function does what the standard view would have done but it has the decorator on it.
def content(request):
if request.user.is_anonymous:
messages.warning(request, 'You must log in to view the course content.')
return content2(request)
@login_required
def content2(request):
return render(request, 'path/template.html')
I am assuming that your log in template already displays messages.
Like I said, it’s a bit of a hack but it works really well.
I am using Django version 3.0.6
- [Django]-Python/django – "Cannot use ImageField because Pillow is not installed"
- [Django]-Using a mixin with a Django form class
- [Django]-Django: How should I store a money value?
0👍
#Create a decorators.py and use the below code
from django.contrib import messages
def login_required(fn):
def wrapper(request,*args,**kwargs):
if request.user.is_anonymous:
messages.success(request,"Sorry! You are not logged in")
return redirect("login")
else:
return fn(request,*args,**kwargs)
return wrapper
#Import the custom decorator on your views
from app_name.decorators import login_required
@login_required
def log_out(request):
logout(request)
messages.success(request,"Successfully logged out!!!")
return redirect('login')````
Note: @login_required will work only on function function based views and if you are using class based views, you can use method decorators like the example below:
from app_name.decorators import login_required
from django.utils.decorators import method_decorator
@method_decorator(login_required, name='dispatch')
class YourClassBasedView(TemplateView):
Hope this will help you!
- [Django]-Python and Django OperationalError (2006, 'MySQL server has gone away')
- [Django]-Fields.E304 Reverse accessor clashes in Django
- [Django]-How to use Django 1.8.5 ORM without creating a django project?
-2👍
I know it’s old but it can still help others
I think to redirect an unconnected user to the login page and at the same time send a message you can proceed as follows:
from django.contrib import messages
def views(request):
if request.user.is_anonymous:
messages.add_message(request, messages.INFO,
'You must be logged in')
return redirect('your_login_views')
else:
# do smothing
return redirect(request, 'your_page.html')
- [Django]-Django admin interface: using horizontal_filter with inline ManyToMany field
- [Django]-How to use Django model inheritance with signals?
- [Django]-DRF: Simple foreign key assignment with nested serializers?
-4👍
Try using this: http://code.google.com/p/django-session-messages/
or use Django 1.2 (currently in Beta) and the messages framework: http://docs.djangoproject.com/en/dev/ref/contrib/messages/#ref-contrib-messages
- [Django]-Django: Check if settings variable is set
- [Django]-Putting a django login form on every page
- [Django]-Logging requests to django-rest-framework