[Django]-Pass a list as a parameter to django tag

8👍

There are basically two approaches here:

  1. trying to construct a list, one way or another, and pass it to my_tag; or
  2. change my_tag such that passing a list is more convenient.

Constructing lists

Django templates offer ways to construct a list, although most of these are rather limited.

Using the make_list template filter

Django for example introduces a make_list template filter [Django-doc] that takes an iterable, and converts it to a list of the items. For example we can use the template filter with:

{% my_tag paramA='asdf' paramB='fdsa' listparams='XY'|make_list %}

But there are two potential problems with this: (1) for a string it iterates over the characters, so the elements will all be 1-character strings, and (2) you can not construct lists that contain integers, etc. unless you already have a collection-like object, but this would basically make the make_list useless.

Using .split()

We can solve the problem that it only takes 1-character strings, by performing a call to .split(), this works only for strings (unless the type of the variable also supports a .split() function), so we can solve the problem with mulit-char parts with:

{% my_tag paramA='asdf' paramB='fdsa' listparams='XY Z'.split %}

Implement a custom variadic tag to construct lists

We can also define a variadic tag, that first construct a list. We do this by implementing a custom tag:

#  app/templatetags/create_list.py

from django import template

register = template.Library()

@register.simple_tag
def create_list(*args):
    return args

We can then use two steps to pass a list:

{% load create_list %}
{% create_list 'X' 'Y' as mylist %}
{% my_tag paramA='asdf' paramB='fdsa' listparams=mylist %}

Changing my_tag

Perhaps a clean way could be to make use of positional parameters here to obtain the list. A function in Python has two types of parameters: positional ones (the ones passed without the name of the parameter), and named ones (the ones with key=...).

We can thus use the positional ones here for the list, and thus call the tag with:

{% my_tag 'X' 'Y' paramA='asdf' paramB='fdsa' %}

In case we do not mention any positional parameters, the list is thus considered empty. We can pass an arbitrary number of parameters.

We can for example implement the tag as:

#  app/templatetags/my_tag.py

from django import template

register = template.Library()

@register.simple_tag
def my_tag(*listparams, paramA=None, paramB=None):
    # ... processing
    return None

A potential problem with this approach is that we can only perform this “trick” once, in the sense that we can not define two separate such *args. We can of course aim to split the *args into two lists, but this can be tricky.

Leave a comment