Django template filter to create a list of items that are comma-separated and end with "and"

It seems to me that I am writing something that should already exist.

Is there a template filter in Django that combines a list of elements in commas and places and 'and' before the last?

For instance:

a = ['foo',] b = ['bar', 'baz',] c = a + b d = c + ['yourmom',] 

The filter I'm looking for will display each list in the following ways:

a will display 'foo'.
b will display "bar and baz".
c will display "foo, bar and baz".
d will display "foo, bar, baz and yourmom".

QUESTION 1: Is there something that does this already?


I tried to write this myself, and it breaks into two places:

My code: http://pastie.org/private/fhtvg5tchtwlnrdyuoyeja

QUESTION 2: it splits into forloop.counter and tc.author.all | length. Please explain why they are invalid.

+4
source share
4 answers

You can do this in your template:

 {% for item in list %} {% if forloop.first %}{% else %} {% if forloop.last %} and {% else %}, {% endif %} {% endif %}{{item}} {% endfor %} 


line breaks have been added for clarity: delete them to avoid unwanted spaces in your output:

 {% for item in list %}{% if forloop.first %}{% else %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}{{item}}{% endfor %} 


Edit: Modified code. Thanks to Eric Fortin for noticing that I was embarrassed.

+14
source

Here is one that I wrote using the "max items" function:

 useserialcomma = True def listify(values, maxitems=4): sercomma = ',' if useserialcomma else '' l = len(values) if l == 0: return '' elif l == 1: return values[0] elif l == 2: return values[0] + ' and ' + values[1] elif l <= maxitems: return ', '.join(values[:l-1]) + sercomma + ' and ' + values[-1] else: andmoretxt = ' and %d more' % (l - maxitems) return ', '.join(values[:maxitems]) + andmoretxt 

This filter allows you to specify the maximum number of elements that you want to display. So, given this list:

 myitems = ['foo', 'bar', 'baz', 'barn', 'feast', 'pizza'] 

this code in your template:

 {{ myitems|listify:3 }} 

gives:

 foo, bar, baz and 3 others 
0
source

I solved this problem using css ::before and ::after pseudo-classes. I gave each element an item class, and then did the following:

 .item:not(:last-child)::after{ content: ", "; } .item:last-child::before{ content: "and "; } .item:last-child::after{ content: "."; } 

This is not a Django solution, but it is always helpful to post a pot of ideas.

0
source

Try a filter like this (not tested):

 def human_join(values): out = ', '.join(values[:-1]) if out: out += ' and ' if values: out += values[-1] return out 
-1
source

All Articles