Django模板过滤器,用于创建以逗号连接并以“结束”结尾的项目列表;及;

Django模板过滤器,用于创建以逗号连接并以“结束”结尾的项目列表;及;,django,django-templates,Django,Django Templates,我觉得我在写一些应该已经存在的东西 Django是否有一个模板过滤器,可以在最后一个项目之前加入逗号、位置和“and”的项目列表 例如: a = ['foo',] b = ['bar', 'baz',] c = a + b d = c + ['yourmom',] 我正在查找的筛选器将以以下方式显示每个列表: a将显示“foo” b将显示“bar and baz” c将显示“foo、bar和baz” d将显示“foo、bar、baz和你妈妈” 问题1:已经有这样的东西了吗? 我试着自己写这篇

我觉得我在写一些应该已经存在的东西

Django是否有一个模板过滤器,可以在最后一个项目之前加入逗号、位置和“and”的项目列表

例如:

a = ['foo',]
b = ['bar', 'baz',]
c = a + b
d = c + ['yourmom',]
我正在查找的筛选器将以以下方式显示每个列表:

a将显示“foo”
b将显示“bar and baz”
c将显示“foo、bar和baz”
d将显示“foo、bar、baz和你妈妈”

问题1:已经有这样的东西了吗?


我试着自己写这篇文章,它在两个地方被打破了:

我的代码:

问题2:它在forloop.counter和tc.author.all长度上中断。请解释这些无效的原因。

请尝试这样的过滤器(未测试):


您可以在模板中执行此操作:

{% for item in list %}
    {% if forloop.first %}{% else %}
        {% if forloop.last %} and {% else %}, {% endif %}
    {% endif %}{{item}}
{% endfor %}
{{ myitems|listify:3 }}

为清晰起见添加了换行符:删除它们以避免输出中出现不必要的空格:


编辑:更改代码。感谢Eric Fortin让我注意到自己被搞糊涂了。

我写了一个带有“最大项目”功能的:

模板中的以下代码:

{% for item in list %}
    {% if forloop.first %}{% else %}
        {% if forloop.last %} and {% else %}, {% endif %}
    {% endif %}{{item}}
{% endfor %}
{{ myitems|listify:3 }}
产生:

foo, bar, baz and 3 others

我使用css
::before
::after
伪类解决了这个问题。我给每个项目上了一堂
item
课,然后这样做:

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

这不是Django的解决方案,但是激发大量的想法总是好的。

你在
tc.author.all | length
中遇到了什么错误?此外,您可以考虑使用<代码>长度>代码>作者。所有。计数< /代码>您的示例使用“牛津逗号”,也称为“串行逗号”。这是“三”或“更多”项中的“和”之前的额外逗号。例如,“foo、bar和baz”对于两个项目是正确的,但是“foo和bar”(不带逗号)对于两个项目是正确的。幸运的是,为其编写单元测试并不重要。到目前为止,所有的解决方案都失败了。事实上,我认为需要像这样反转:{%if-forloop.last%}和{%else%},{%endif%}{{item}}并且我们还需要第一个if来检查第一个元素,以避免在第一个示例中显示“foo和”。所以:{%if-forloop.first%}{{item}{%else%}{%if-forloop.last%}和{%else%},{%endif%}{{item}{%endif%}谢谢你的帖子。我觉得瘸了。我想我想我想得太多了。
foo, bar, baz and 3 others
.item:not(:last-child)::after{
    content: ", ";
}
.item:last-child::before{
    content: "and ";
}
.item:last-child::after{
    content: ".";
}