1

I write a custom tag for using in django templates: {% my_custom_tag %}.

Using django channels it extends some page functionality. But I a worried that users may by accident insert this tag twice to a template, and that can create some issues because channels will deliver the same info twice etc.

Is there any relatively simple way to check that the tag is used in a template only once and raise an error otherwise?

Philipp Chapkovski
  • 1,949
  • 3
  • 22
  • 43

1 Answers1

1

You could maniplate the context, and set a certain key (preferably one that is not used by other applications) to True, and raise an exception otherwise. For example:

@register.simple_tag(takes_context=True)
def my_custom_tag(context):
    if '__some_weird_name__for_my_custom_tag' in context:
        raise Exception('my_custom_tag is already used')
    context['__some_weird_name__for_my_custom_tag'] = True
    # ...
    # do other logic
    pass

Of course the condition is that you do not pass content with this name to the context initially.

Furthermore if you would perform multiple render(..)s in a view, these will usually have a separate context, but this is probably desired.

Note that the error is raised at runtime. We thus do not proactively detect templates where this happens, but we will get an error if it happens.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • I like your approach. But I have a question: the same functionality is available in {% extends %} tag in django: when we use it more than once it raises the error. The way they did it is this (just copy pasted from django source): https://gist.github.com/chapkovski/5c7c34667882c3a159cfdc0aa515a4a2 Isn't it better? – Philipp Chapkovski Aug 10 '18 at 13:09
  • @PhilippChapkovski: well this does not guarantee that it occurs more than twice: it guantees that it does not occurs more than once *per file*. That is something different. For example the file can `{% extends otherfile.html %}`, and the `otherfile.html` can contain an extra `{% extends andanotherfile.html %}`. You thus "parse" the Abstract Syntax tree of a file. – Willem Van Onsem Aug 10 '18 at 13:11
  • @PhilippChapkovski: see for example here: https://gist.github.com/joar/4f1aa693c9a29c0d1deb – Willem Van Onsem Aug 10 '18 at 13:15
  • ah, I see, you are absolutely right. It may also contain {% include %} pointing to a file using {% my_custom_tag %} as well - and you approach also blocks this. Cool, thanks!! – Philipp Chapkovski Aug 10 '18 at 13:15