[Django]-Macros in django templates

31👍

As you already said macros don’t exist in django’s templating languages.

There are template tags to do more difficult things in templates, but that’s not what you’re looking for either, because django’s templating system also doesn’t allow parameters being passed to functions.

The best thing for your example would be to use the include tag:
https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#include

Here’s how I would use it:

templates/snippets/list.html

<ul>
{% for item in list %}
   <li>{{ item }}</li>
{% endfor %}
</ul>

templates/index.html

{% include 'snippets/list.html' with list=list1 %}
{% include 'snippets/list.html' with list=list2 %}
{% include 'snippets/list.html' with list=list3 %}
...

5👍

I found two packages to offer that:

they both look to work the same: install with pip, put in INSTALLED_APPS, {% load macros %} in the template, write and use them.

4👍

template/partials/example-partial.html

{%if partial_name == 'partial1'%}
<ul>
{% for item in list %}
   <li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}


{%if partial_name == 'partial2'%}
<ul>
{% for item in list %}
   <li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}


{%if partial_name == 'partial3'%}
<ul>
{% for item in list %}
   <li>{{ item }}</li>
{% endfor %}
</ul>
{%endif%}

templates/index.html

{% include 'partials/example-partial.html' with list=list1 partial_name="partial1"%}
{% include 'partials/example-partial.html' with list=list2 partial_name="partial2"%}
{% include 'partials/example-partial.html' with list=list3 partial_name="partial3"%}

1👍

… just start using jinja with Django.
it’s very easy to turn it on
and you can use both template engines at the same time, of course for different files.

0👍

In the Django Template Language macros are not supported, but you can select the Jinja engine in order to use macros. Keep in mind that if you are building a plugable application, Django recommends using the DTL.

A Django project can be configured with one or several template
engines (or even zero if you don’t use templates). Django ships
built-in backends for its own template system, creatively called the
Django template language (DTL), and for the popular alternative
Jinja2.

The Django template language is Django’s own template system. Until
Django 1.8 it was the only built-in option available. It’s a good
template library even though it’s fairly opinionated and sports a few
idiosyncrasies. If you don’t have a pressing reason to choose another
backend, you should use the DTL, especially if you’re writing a
pluggable application and you intend to distribute templates. Django’s
contrib apps that include templates, like django.contrib.admin, use
the DTL.

Here is the link to the documentation for configuring other template engines: https://docs.djangoproject.com/en/dev/topics/templates/#configuration

0👍

If you simply want to render different items in the same way, then you don’t need macro, include tag will suffice, as Chris suggested in another answer.

If you want to apply the same wrapping/processing around arbitrary content, then you can do this with custom template tag that reads content between opening and closing tags. Refer to do_upper tag example in Django docs. One more example is template tag for fancy wrapping of list items:

# Usage
{% custom_list is_pretty=True %}
  <li class="custom-class-1">item1</li>
  <li class="custom-class-2">item2</li>
{% end_custom_list %}

# templatetags
from django import template

register = template.Library()


@register.tag
def custom_list(parser, token):
    nodelist = parser.parse(("end_custom_list",))
    parser.delete_first_token()

    items = token.split_contents()
    tag_name = items[0]
    params = {}
    for item in items[1:]:
        name, val = item.split("=")
        params[name] = val
    is_pretty = params.get("is_pretty") in ("True", "1")
    unsupported_params = set(params.keys()) - {"is_pretty",}
    if unsupported_params:
        raise template.TemplateSyntaxError(
            "Unsupported parameters passed to %s tag: %s"
            % (tag_name, unsupported_params)
        )
    return _CustomListNode(nodelist, is_pretty)


class _CustomListNode(template.Node):
    def __init__(self, nodelist, is_pretty):
        self.nodelist = nodelist
        self.params = {
            "is_pretty": is_pretty,
        }

    def render(self, context):
        inner = self.nodelist.render(context)
        t = context.template.engine.get_template("custom_list.html")
        content = t.render(
            template.Context(
                {
                    "inner": inner,
                    **self.params,
                },
                autoescape=context.autoescape,
            )
        )
        return content
        
        
# custom_list.html
<div>some header</div>
<ul class="custom {% if is_pretty %}pretty{% endif %}">
  {{ inner }}
</ul>
<div>some footer</div>        

Leave a comment