diff options
| author | Jake Howard <RealOrangeOne@users.noreply.github.com> | 2024-11-19 17:35:02 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-11-19 14:35:02 -0300 |
| commit | 4c452cc377f6f43acd90c6e54826ebd2e6219b0d (patch) | |
| tree | ad216420ba1d3564e736add4e5716fe259168137 /django/template | |
| parent | 9543c605c38b80b3ace3836b110e9e1938a44a97 (diff) | |
Fixed #35535 -- Added template tag decorator simple_block_tag().
Co-authored-by: Natalia <124304+nessita@users.noreply.github.com>
Diffstat (limited to 'django/template')
| -rw-r--r-- | django/template/library.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/django/template/library.py b/django/template/library.py index 4ee96cea89..d181caa832 100644 --- a/django/template/library.py +++ b/django/template/library.py @@ -153,6 +153,90 @@ class Library: else: raise ValueError("Invalid arguments provided to simple_tag") + def simple_block_tag(self, func=None, takes_context=None, name=None, end_name=None): + """ + Register a callable as a compiled block template tag. Example: + + @register.simple_block_tag + def hello(content): + return 'world' + """ + + def dec(func): + nonlocal end_name + + ( + params, + varargs, + varkw, + defaults, + kwonly, + kwonly_defaults, + _, + ) = getfullargspec(unwrap(func)) + function_name = name or func.__name__ + + if end_name is None: + end_name = f"end{function_name}" + + @wraps(func) + def compile_func(parser, token): + tag_params = params.copy() + + if takes_context: + if len(tag_params) >= 2 and tag_params[1] == "content": + del tag_params[1] + else: + raise TemplateSyntaxError( + f"{function_name!r} is decorated with takes_context=True so" + " it must have a first argument of 'context' and a second " + "argument of 'content'" + ) + elif tag_params and tag_params[0] == "content": + del tag_params[0] + else: + raise TemplateSyntaxError( + f"'{function_name}' must have a first argument of 'content'" + ) + + bits = token.split_contents()[1:] + target_var = None + if len(bits) >= 2 and bits[-2] == "as": + target_var = bits[-1] + bits = bits[:-2] + + nodelist = parser.parse((end_name,)) + parser.delete_first_token() + + args, kwargs = parse_bits( + parser, + bits, + tag_params, + varargs, + varkw, + defaults, + kwonly, + kwonly_defaults, + takes_context, + function_name, + ) + + return SimpleBlockNode( + nodelist, func, takes_context, args, kwargs, target_var + ) + + self.tag(function_name, compile_func) + return func + + if func is None: + # @register.simple_block_tag(...) + return dec + elif callable(func): + # @register.simple_block_tag + return dec(func) + else: + raise ValueError("Invalid arguments provided to simple_block_tag") + def inclusion_tag(self, filename, func=None, takes_context=None, name=None): """ Register a callable as an inclusion tag: @@ -243,6 +327,23 @@ class SimpleNode(TagHelperNode): return output +class SimpleBlockNode(SimpleNode): + def __init__(self, nodelist, *args, **kwargs): + super().__init__(*args, **kwargs) + self.nodelist = nodelist + + def get_resolved_arguments(self, context): + resolved_args, resolved_kwargs = super().get_resolved_arguments(context) + + # Restore the "content" argument. + # It will move depending on whether takes_context was passed. + resolved_args.insert( + 1 if self.takes_context else 0, self.nodelist.render(context) + ) + + return resolved_args, resolved_kwargs + + class InclusionNode(TagHelperNode): def __init__(self, func, takes_context, args, kwargs, filename): super().__init__(func, takes_context, args, kwargs) |
