'Show message in Django without needing a request
I have a view which uses threading e.g
from .utils import my_heavy_function
def my_view(request):
if request.method == "POST":
form = my_model_form()
if form.is_valid():
#create thread
thr = threading.Thread(target=my_heavy_function,args=(form,))
thr.start()
messages.success(request, "Processing ...")
return redirect("my_template")
else:
form = my_model_form()
return render(request, "my_app/my_template.html")
and it works like a charm; it process the my_heavy_function
in the background while making the user able to continue using the webpage. I just need a way to show a message when my_heavy_function
is done.
Is there a way to make Django display a message even when a new-request is not called but based on some other condition? E.g on a page when a file is done loading etc.
(I have on purposed not used Django-Q, Celery or back-ground-tasks for this threading since I find it being overkill)
Solution 1:[1]
It's not very clear what do you want to do. If you want to notify user without it doing an HTTP request, your only bet in web technologies is to setup a WebSocket so you can push things from server.
If it's ok for user to get the message next time they open a page, you can put something in the DB when your heavy task is done. And on each request you check if you have something in DB, you'll do messages.add_message
and remove that row from DB.
Solution 2:[2]
If you want to show the message with a result of an action, that has finished after a response to the request has been returned, you have this option to show it synchronically.
The way it works is that next time the user requests a resource, this implementation will check for any messages for this user, that has been created meanwhile (eg. after your async code finished execution and added a message.
This solution uses a superstructure to the synchronous Django messaging framework with a simple Memcache container.
Install memcached as your cache backend.
docker run -p 11211:11211 --name local-memcache -d memcached memcached -m 64
Then go and
pip install django-async-messages django-pymemcache
Add this to your
middleware
insettings.py
file:'async_messages.middleware.AsyncMiddleware'
Ensure it comes after 'django.contrib.messages.middleware.MessageMiddleware'
Then add this to your
settings.py
file:CACHES = { 'default': { 'BACKEND': 'djpymemcache.backend.PyMemcacheCache', 'LOCATION': [ '127.0.0.1:11211', ], }, }
Where you want to use this async messaging, go
from async_messages import message_user
Substitute your classicalmessages.add_message(...
formessage_user(request.user, "your message")
where first agrument is a user objectgo to the
django-async-messages
package because it is slightly obsolete and needs a small update. Locate themiddleware.py
file in the package (likely invenv/Lib/site-packages/async_messages/middleware.py
)Change it from this
from django.contrib import messages
from async_messages import get_messages
class AsyncMiddleware(object):
def process_response(self, request, response): """ Check for messages for this user and, if it exists, call the messages API with it """ if hasattr(request, "session") and hasattr(request, "user") and request.user.is_authenticated(): msgs = get_messages(request.user) if msgs: for msg, level in msgs: messages.add_message(request, level, msg) return response
to this:
from django.contrib import messages
from async_messages import get_messages
from django.utils.deprecation import MiddlewareMixin
class AsyncMiddleware(MiddlewareMixin):
def process_response(self, request, response):
"""
Check for messages for this user and, if it exists,
call the messages API with it
"""
if hasattr(request, "session") and hasattr(request, "user") and request.user.is_authenticated:
msgs = get_messages(request.user)
if msgs:
for msg, level in msgs:
messages.add_message(request, level, msg)
return response
That is it - you have asynchronous messaging!
Ps - because you just edited a package which would change when deploying - I exctracted the package and with above changes I included it directly in my project structure.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Arman Ordookhani |
Solution 2 | David Louda |