I need a button, included in the header of every page in my Django application, to trigger some global method, to toggle a "mode
" setting in the session. There are two modes: 'preview' and 'publish'.
One solution I've come up with: duplicate a post()
method in every (class-based) view, to handle the mode change. This hardly seems DRY.
Another would be to inherit all of my CBVs from a single superclass, or use a mixin. I suppose this is a possibility.
A better solution perhaps: I've setup a context_processor
to handle publishing the mode globally to my templates. This works fine. I've also setup a middleware
class with process_request
which could, theoretically, handle POST
requests globally. But how do I call this process_request
method from my templates?
My current stab at it follows. How do I toggle the "preview" and "publish" buttons in my template, and call the middleware?
template.html
:
<html>
<head></head>
<body>
<header>
<form method="post">
{% csrf_token %}
<!-- button toggle -->
{% if mode == 'preview' %}
<button name="mode" value="publish">Publish</button>
{% else %}
<button name="mode" value="preview">Preview</button>
{% endif %}
</form>
</header>
</body>
</html>
middleware.py
:
class MyMiddleware(object):
def process_request(self, request):
update_mode(request)
def update_mode(request, new_mode=None): # how do I call this from template?
modes = [
'preview',
'publish'
]
# ensure default
if not request.session.get('mode', None):
request.session['mode'] = 'preview'
# set new mode
if new_mode and new_mode in modes:
request.session['mode'] = new_mode
context_processor.py
:
def template_mode(request):
context = {
'mode': request.session['mode']
}
return context
You don't "call" middleware: that's not at all how it works. Middleware is invoked on every request, so in your case the update_mode function would always run.
A better solution would be to get the form containing the button to post to a new URL, which invokes a view to update the mode. You could add a hidden field containing the current URL - which you can get from
request.path
- and the update mode view can redirect back to that URL after doing its work.