Reputation: 3271
I want to conditionally clear django.contrib.messages
. None of the solutions discussed in these two questions work:
Delete all django.contrib.messages
Django: Remove message before they are displayed
Any suggestions on how I can clear the messages? I am using django 1.10
Code:
messages = get_messages(request)
for msg in messages:
pass
for msg in messages._loaded:
del msg
for msg in messages._queued_messages:
del msg
Upvotes: 12
Views: 12818
Reputation: 31
Even it is not recommended to access protected members of a class. As worked solution for me was:
messages.get_messages(action_context.request)._queued_messages.clear()
When you run messages.get_messags(request)
it returns a <django.contrib.messages.storage.fallback.FallbackStorage at 0x740f45f349b0>
object which has a following attributes:
fallback_storage = messages.get_messages(action_context.request)
fallback_storage
Out[3]: <django.contrib.messages.storage.fallback.FallbackStorage at 0x740f45f349b0>
fallback_storage.__dict__
Out[4]:
{'request': <WSGIRequest: POST '/a/login/'>,
'_queued_messages': [<django.contrib.messages.storage.base.Message at 0x740f31d7eef0>],
'used': False,
'added_new': True,
'storages': [<django.contrib.messages.storage.cookie.CookieStorage at 0x740f33b65588>,
<django.contrib.messages.storage.session.SessionStorage at 0x740f33b65a58>],
'_used_storages': set(),
'_level': 20,
'_loaded_data': []}
I recommend to clear directly the _queued_messaged
instead of clearing storages
as you may delete unexpected data in SessionStorage
or CookieStorage
Upvotes: 0
Reputation: 887
After digging through the code and experimenting a bit, I discovered the issue frustrating everyone here is that, when the test client is running, the messages are being stored in a cookie. So in between requests there are no messages anywhere "server side" to clear out.
But you can delete the "messages" cookie:
# A view which sets messages, but doesn't render them
response = self.client.get('/a/path')
# Messages are stored in a cookie which the client holds and will send on the next request
print(f'messages cookie: {self.client.cookies["messages"].value}')
# Remove the messages cookie:
self.client.cookies.pop('messages')
# Or:
response.delete_cookie('messages')
Upvotes: 0
Reputation: 1
To clear messages from the Django messages storage, you can use the storage.used
attribute after iterating through the messages. This attribute marks the messages as used, effectively clearing them from the storage.
from django.contrib import messages
def custom_login(request):
error_message = None # Initialize error message variable
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(request, username=username, password=password)
storage = messages.get_messages(request)
for message in storage:
print(message) # Optional: Print messages for debugging or logging purposes
storage.used = True # Mark messages as used to clear them from storage
if user is not None:
login(request, user)
next_url = request.POST.get('next') or reverse('home')
return redirect(next_url)
else:
error_message = 'Invalid username or password.'
messages.error(request, error_message)
return render(request, 'login.html', {'error_message': error_message})
Django 4
Upvotes: 0
Reputation: 2921
This is the only thing (other than overriding the messages
block in the template) that worked for me in Django 4.*:
from django.contrib.messages.storage import default_storage
request._messages = default_storage(request)
This is basically re-initialising the storage (like the messages middleware does).
Upvotes: 6
Reputation: 215
I am on Django 3.2 and none of the answers given here worked for me. Don't know why. Maybe it might be due to some changes in the newer versions. So I figured out a way to do this. If you need to delete the messages or you don't want to show the messages on a certain template, just iterate over the messages without doing anything in the template file.
{% if messages %}
{% for message in messages %}
{% endfor %}
{% endif %}
I added these lines in the template in which the messages should be deleted. Doing this in views is not possible now I guess. Still looking up for more insights on this by the community.
Upvotes: 1
Reputation: 121
You need to iterate through the messages for your current set of messages as retrieved from the 'get_messages' method. You can use this code anywhere you want to clear the messages before setting new ones or where you want to simply clear all messages.
system_messages = messages.get_messages(request)
for message in system_messages:
# This iteration is necessary
pass
Note: If you do not want to clear messages, then set the system_messages.used flag to 'False' as the messages are marked to be cleared when the storage instance is iterated (and cleared when the response is processed). Reference: https://docs.djangoproject.com/en/3.0/ref/contrib/messages
Upvotes: 12
Reputation: 2454
A one-liner would look like this:
list(messages.get_messages(request))
It essentially performs the same task as @Avukonke Peter's solution. However, I didn't find it necessary to set the messages as used (I believe this is done by default, but feel free to correct me if I'm wrong). It's beyond me why there's no messages.clear()
function.
Upvotes: 15