I have a custom inclusion tag in Django, and I need to pass there a list as a parameter. Something along these lines:
{% my_tag paramA='asdf' paramB='fdsa' listparams=['X', 'Y'] %}
This of course does not work because Django does not know how to deal with lists passed that way.
I can also capture something general like list_ and then combine them into a list on a server side:
{% my_tag paramA='asdf' paramB='fdsa' list_1='X' list_2='Y' list_3='Z' %}
But I wonder if there is a nicer way of dealing with this.
There are basically two approaches here:
my_tag; ormy_tag such that passing a list is more convenient.Django templates offer ways to construct a list, although most of these are rather limited.
make_list template filterDjango 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.
.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 %}
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 %}
my_tagPerhaps 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With