Django模板过滤器创建以逗号连接并以“and”结尾的项目列表

Posted

技术标签:

【中文标题】Django模板过滤器创建以逗号连接并以“and”结尾的项目列表【英文标题】:Django template filter to create an list of items that join on commas and end on "and" 【发布时间】:2011-03-25 13:19:47 【问题描述】:

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

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

例如:

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 和 yourmom”。

问题 1:有什么东西已经这样做了吗?


我尝试自己写这个,但它在两个地方出现了问题:

我的代码: http://pastie.org/private/fhtvg5tchtwlnrdyuoyeja

问题 2:它在 forloop.counter & tc.author.all|length 上中断。请解释为什么这些无效。

【问题讨论】:

tc.author.all|length 出现什么错误?此外,您可以考虑使用 tc.author.all.count 而不是 |length 您的示例使用“Oxford comma”,也称为“Serial comma”。这是三个或更多项目列表中“和”之前的额外逗号。即,“foo、bar 和 baz”对于两个项目是正确的,但“foo 和 bar”(没有逗号)对于两个项目是正确的。幸运的是,为此编写单元测试是微不足道的。到目前为止,以下解决方案都失败了。 【参考方案1】:

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

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

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

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

编辑:更改了代码。感谢 Eric Fortin 让我注意到我很困惑。

【讨论】:

其实我觉得需要这样反转:% if forloop.last % and % else %, % endif %item 我们还需要一个首先如果检查第一个元素以避免在第一个示例中显示“foo and”。所以:% if forloop.first %item% else %% if forloop.last % 和 % else %, % endif %item% endif % 感谢发帖。我觉得很蹩脚。我想我想多了。【参考方案2】:

这是我用“最大项目”功能写的一个:

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

此过滤器可让您指定要显示的最大项目数。因此,鉴于此列表:

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

模板中的这段代码:

 myitems|listify:3 

产生:

foo, bar, baz and 3 others

【讨论】:

【参考方案3】:

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

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

    if values:
        out += values[-1]

    return out

【讨论】:

【参考方案4】:

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

.item:not(:last-child)::after
    content: ", ";

.item:last-child::before
    content: "and ";

.item:last-child::after
    content: ".";

这不是一个 Django 解决方案,但激发灵感总是好的。

【讨论】:

以上是关于Django模板过滤器创建以逗号连接并以“and”结尾的项目列表的主要内容,如果未能解决你的问题,请参考以下文章

是否有 django 模板过滤器来显示百分比?

模板继承and自定义模板标签和过滤器

我试图在数字数组上使用 .filter、.sort 和 .reduce 以返回由逗号和空格分隔的字符串

在 Django 中自定义模板标签以过滤博客中的特色帖子

Django 查询:返回一个将转换为“AND (...)”的 Q 对象

Django 多对多字段过滤器列表