如果fruits
是列表['apples', 'oranges', 'pears']
,
使用django模板标签快速生成“苹果,橘子和梨”吗?
我知道使用循环和{% if counter.last %}
语句执行此操作并不困难,但因为我将反复使用它,我想我将不得不学习如何编写自定义标记过滤器,如果已经完成,我不想重新发明轮子。
作为扩展,我试图放弃Oxford Comma(即返回“苹果,橘子和梨”)甚至更加混乱。
答案 0 :(得分:126)
首选:使用现有的连接模板标记。
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#join
这是他们的例子
{{ value|join:" // " }}
第二选择:在视图中执行。
fruits_text = ", ".join( fruits )
为模板提供fruits_text
以进行渲染。
答案 1 :(得分:63)
这是一个超级简单的解决方案。将此代码放入comma.html:
{% if not forloop.last %}{% ifequal forloop.revcounter 2 %} and {% else %}, {% endifequal %}{% else %}{% endif %}
现在无论你把逗号放在哪里,都要包含“comma.html”:
{% for cat in cats %}
Kitty {{cat.name}}{% include "comma.html" %}
{% endfor %}
答案 2 :(得分:34)
我建议自定义django模板过滤器而不是自定义标记 - 过滤器更方便,更简单(在适当的地方,就像这里一样)。 {{ fruits | joinby:", " }}
看起来就像我想要的那样...使用自定义joinby
过滤器:
def joinby(value, arg):
return arg.join(value)
正如你所看到的那样简单!
答案 3 :(得分:21)
在Django模板上,您需要做的就是在每个水果之后建立一个逗号。一旦它到达最后一个果实,逗号就会停止。
{% if not forloop.last %}, {% endif %}
答案 4 :(得分:7)
这是我为解决我的问题所写的过滤器(它不包括牛津逗号)
def join_with_commas(obj_list):
"""Takes a list of objects and returns their string representations,
separated by commas and with 'and' between the penultimate and final items
For example, for a list of fruit objects:
[<Fruit: apples>, <Fruit: oranges>, <Fruit: pears>] -> 'apples, oranges and pears'
"""
if not obj_list:
return ""
l=len(obj_list)
if l==1:
return u"%s" % obj_list[0]
else:
return ", ".join(str(obj) for obj in obj_list[:l-1]) \
+ " and " + str(obj_list[l-1])
要在模板中使用它:{{ fruits|join_with_commas }}
答案 5 :(得分:4)
如果你想要一个'。'在Michael Matthew Toomim的回答结束时,然后使用:
{% if not forloop.last %}{% ifequal forloop.revcounter 2 %} and {% else %}, {% endifequal %}{% else %}{% endif %}{% if forloop.last %}.{% endif %}
答案 6 :(得分:2)
此处的所有答案均无法通过以下一项或多项操作:
and
。这是我进入该经典的时间。首先,测试:
class TestTextFilters(TestCase):
def test_oxford_zero_items(self):
self.assertEqual(oxford_comma([]), '')
def test_oxford_one_item(self):
self.assertEqual(oxford_comma(['a']), 'a')
def test_oxford_two_items(self):
self.assertEqual(oxford_comma(['a', 'b']), 'a and b')
def test_oxford_three_items(self):
self.assertEqual(oxford_comma(['a', 'b', 'c']), 'a, b, and c')
现在是代码。是的,它有点混乱,但是您会发现它不使用负索引:
from django.utils.encoding import force_text
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
@register.filter(is_safe=True, needs_autoescape=True)
def oxford_comma(l, autoescape=True):
"""Join together items in a list, separating them with commas or ', and'"""
l = map(force_text, l)
if autoescape:
l = map(conditional_escape, l)
num_items = len(l)
if num_items == 0:
s = ''
elif num_items == 1:
s = l[0]
elif num_items == 2:
s = l[0] + ' and ' + l[1]
elif num_items > 2:
for i, item in enumerate(l):
if i == 0:
# First item
s = item
elif i == (num_items - 1):
# Last item.
s += ', and ' + item
else:
# Items in the middle
s += ', ' + item
return mark_safe(s)
您可以在django模板中使用以下命令:
{% load my_filters %}
{{ items|oxford_comma }}
答案 7 :(得分:1)
Django没有支持这种开箱即用的功能。您可以为此定义自定义过滤器:
from django import template
register = template.Library()
@register.filter
def join_and(value):
"""Given a list of strings, format them with commas and spaces, but
with 'and' at the end.
>>> join_and(['apples', 'oranges', 'pears'])
"apples, oranges, and pears"
"""
# convert numbers to strings
value = [str(item) for item in value]
if len(value) == 1:
return value[0]
# join all but the last element
all_but_last = ", ".join(value[:-1])
return "%s, and %s" % (all_but_last, value[-1])
但是,如果您想要处理比字符串列表更复杂的事情,则必须在模板中使用明确的{% for x in y %}
循环。
答案 8 :(得分:1)
在将import { decorate, observable } from 'mobx'
import { serializable, primitive } from 'serializr'
import persist from 'mobx-persist';
class Todo {
id = Math.random();
title = "";
finished = false;
}
decorate(Todo, {
title: [serializable(primitive), persist('object'), observable],
finished: observable
})
作为上下文数据发送到模板之前,我会简单地使用它。
更新:
', '.join(['apples', 'oranges', 'pears'])
您将获得data = ['apples', 'oranges', 'pears']
print(', '.join(data[0:-1]) + ' and ' + data[-1])
的输出。
答案 9 :(得分:0)
如果你喜欢单行:
@register.filter
def lineup(ls): return ', '.join(ls[:-1])+' and '+ls[-1] if len(ls)>1 else ls[0]
然后在模板中:
{{ fruits|lineup }}
答案 10 :(得分:0)
我认为最简单的解决方案可能是:
@register.filter
def comma_list(p_values: Iterable[str]) -> List[str]:
values = list(p_values)
if len(values) > 1:
values[-1] = u'and %s' % values[-1]
if len(values) > 2:
return u', '.join(values)
return u' '.join(values)