Last active
November 9, 2020 16:25
-
-
Save scott2b/0de7fcd2eccf69cc2f374a9f2b0aa5f2 to your computer and use it in GitHub Desktop.
Request template context with messages for Starlette+Jinja2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{% if request.session.messages %} | |
<ul> | |
{% for message in request.session.messages %} | |
<li>{{ message }}</li> | |
{% endfor %} | |
</ul> | |
{{ request.clear_messages() }} | |
{% endif %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
A custom template renderer for Starlette which injects the local request object | |
into the template context and adds session-based messaging. | |
Requires session middleware to be installed. | |
Use Templates as you would use Starlette's Jinja2Templates, e.g.: | |
``` | |
templates = Templates(directory='templates') | |
``` | |
and: | |
``` | |
return templates.TemplateResponse(template, context) | |
``` | |
The local request (must be named `request`) will be injected into the context. | |
To send 1-shot messages to the user, call: | |
``` | |
add_message(request, message) | |
``` | |
""" | |
import inspect | |
import types | |
from starlette.requests import Request | |
from starlette.templating import Jinja2Templates | |
def _clear_messages(request): | |
"""Call from a template after rendering messages to clear out the current | |
message list. Requires session middleware. | |
""" | |
request.session['messages']= [] | |
return '' | |
def add_message(request, message): | |
"""Add a message to the session messages list.""" | |
if not 'messages' in request.session: | |
request.session['messages'] = [] | |
request.session['messages'].append(message) | |
class Templates(Jinja2Templates): | |
def TemplateResponse( | |
self, | |
name: str, | |
context: dict, | |
**kwargs | |
): | |
"""Render a template response. | |
If it exists and is not already set in the context, injects the | |
request object from the calling scope into the template context. | |
Adds a clear_messages method to the request instance. | |
""" | |
if 'request' in context: | |
req = context['request'] | |
if isinstance(req, Request): | |
req.clear_messages = types.MethodType(_clear_messages, req) | |
else: | |
frame = inspect.currentframe() | |
try: | |
_locals = frame.f_back.f_locals | |
req = _locals.get('request') | |
if req is not None and isinstance(req, Request): | |
context['request'] = req | |
req.clear_messages = types.MethodType(_clear_messages, req) | |
finally: | |
del frame | |
return super().TemplateResponse(name, context, **kwargs) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment