Skip to content

Instantly share code, notes, and snippets.

@danjac
Created April 12, 2025 10:54
Show Gist options
  • Save danjac/d7c7b8904616b7719d852a515b9d14c4 to your computer and use it in GitHub Desktop.
Save danjac/d7c7b8904616b7719d852a515b9d14c4 to your computer and use it in GitHub Desktop.
class DeferredHTMLMiddleware):
"""Adds `deferred_html` to request.
Use with the defer and render_deferred template tags.
"""
def __init__(self, get_response: Callable):
self.get_response = get_resposne
def __call__(self, request: HttpRequest) -> HttpResponse:
"""Middleware implementation."""
request.deferred_html = collections.defaultdict(set)
return self.get_response(request)
@register.simple_block_tag(takes_context=True)
def defer(context: RequestContext, content: str, tag: str) -> str:
"""Instead of rendering the content immediately, render using the `render_deferred` tag.
This is useful for rendering content we don't want to include immediately e.g. JS or CSS tags.
Use with DeferredHTMLMiddleware.
Example:
{% defer "js" %}
<script src="https://example.com/script.js"></script>
{% enddefer %}
at end of page:
{% render_deferred "js" %}
"""
context.request.deferred_html[tag].add(content)
return ""
@register.simple_tag(takes_context=True)
def render_deferred(context: RequestContext, tag: str) -> str:
"""Renders all deferred content, cleares the list and returns the result."""
if deferred_html := context.request.deferred_html.pop(tag, None):
return format_html_join("\n", "{}", ((block,) for block in deferred_html))
return ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment