Created
July 14, 2024 12:36
-
-
Save archatas/82ac88b81bedfcca9578c12d2fd3e3fa to your computer and use it in GitHub Desktop.
A Django template tag decorator for including a dynamically set template with context variables
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
from functools import wraps | |
from inspect import getfullargspec, unwrap | |
from django import template | |
register = template.Library() | |
def dynamic_inclusion_tag(filename=None, func=None, takes_context=None, name=None): | |
""" | |
Register a callable as an inclusion tag: | |
@dynamic_inclusion_tag("results.html") | |
def show_results(poll, *args, **kwargs): | |
choices = poll.choice_set.all() | |
return {"choices": choices} | |
@dynamic_inclusion_tag("results.html", takes_context=True) | |
def show_results(context, poll, *args, **kwargs): | |
choices = poll.choice_set.all() | |
return {"choices": choices} | |
Then use it in the template as following: | |
{% show_results poll %} | |
{% show_results poll using "poll_results.html" %} | |
""" | |
def decorator(func): | |
( | |
params, | |
varargs, | |
varkw, | |
defaults, | |
kwonly, | |
kwonly_defaults, | |
_, | |
) = getfullargspec(unwrap(func)) | |
function_name = name or func.__name__ | |
@wraps(func) | |
def compile_func(parser, token): | |
bits = token.split_contents() | |
tag_name = bits[0] | |
bits = bits[1:] | |
args, kwargs = template.library.parse_bits( | |
parser, | |
bits, | |
params, | |
varargs, | |
varkw, | |
defaults, | |
kwonly, | |
kwonly_defaults, | |
takes_context, | |
function_name, | |
) | |
template_name = filename | |
if len(bits) >= 2 and bits[-2] == "using": | |
template_name = bits[-1][1:-1] # Remove quotes | |
if not template_name: | |
raise template.TemplateSyntaxError( | |
f"{tag_name} tag requires a template name to be specified " | |
f"either in the decorator or using 'using' keyword." | |
) | |
return template.library.InclusionNode( | |
func=func, | |
takes_context=takes_context, | |
args=args, | |
kwargs=kwargs, | |
filename=template_name, | |
) | |
register.tag(function_name, compile_func) | |
return func | |
return decorator |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment