簡體   English   中英

逗號分隔django模板中的列表

[英]Comma separated lists in django templates

如果fruits是列表['apples', 'oranges', 'pears']

有沒有一種使用django模板標簽生成“蘋果,橘子和梨”的快捷方式?

我知道使用循環和{% if counter.last %}語句來做這個並不困難,但因為我將反復使用這個,我想我將不得不學習如何編寫自定義 標簽 過濾器,如果它已經完成,我不想重新發明輪子。

作為延伸,我試圖放棄牛津逗號 (即返回“蘋果,橘子和梨”)甚至更加混亂。

第一選擇:使用現有的連接模板標記。

http://docs.djangoproject.com/en/dev/ref/templates/builtins/#join

這是他們的例子

{{ value|join:" // " }}

第二選擇:在視圖中執行。

fruits_text = ", ".join( fruits )

fruits_text提供給模板進行渲染。

這是一個超級簡單的解決方案。 將此代碼放入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 %}

更新:@ user3748764為我們提供了一個稍微更緊湊的版本,沒有棄用的ifequal語法:

{% if not forloop.first %}{% if forloop.last %} and {% else %}, {% endif %}{% endif %}

請注意,它應該在元素之前使用,而不是之后使用。

我建議使用自定義django模板過濾器而不是自定義標簽 - 過濾器更方便,更簡單(在適當的地方,就像這里一樣)。 {{ fruits | joinby:", " }} {{ fruits | joinby:", " }}看起來就像我想要的那樣......使用自定義joinby過濾器:

def joinby(value, arg):
    return arg.join(value)

正如你所看到的那樣簡單!

在Django模板上,您需要做的就是在每個水果之后建立一個逗號。 一旦達到最后的果實,逗號就會停止。

{% if not forloop.last %}, {% endif %}

這是我為解決我的問題所寫的過濾器(它不包括牛津逗號)

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 }}

如果你想要一個'。' 在Michael Matthew Toomim的回答結束時,然后使用:

{% if not forloop.last %}{% ifequal forloop.revcounter 2 %} and {% else %}, {% endifequal %}{% else %}{% endif %}{% if forloop.last %}.{% endif %}

此處的所有答案均不符合以下一項或多項:

  • 他們重寫了標准模板庫中的東西(很差!)(確認,最佳答案!)
  • 他們不使用and最后一項。
  • 他們缺少連續(牛津)逗號。
  • 它們使用負索引,這對django查詢集不起作用。
  • 他們通常不能正確處理弦樂衛生。

這是我進入這個經典。 一,測試:

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 }}

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 %}循環。

在將其作為上下文數據發送到模板之前', '.join(['apples', 'oranges', 'pears'])我會簡單地使用', '.join(['apples', 'oranges', 'pears'])

更新:

data = ['apples', 'oranges', 'pears']
print(', '.join(data[0:-1]) + ' and ' + data[-1])

你會得到apples, oranges and pears輸出。

如果你喜歡單行:

@register.filter
def lineup(ls): return ', '.join(ls[:-1])+' and '+ls[-1] if len(ls)>1 else ls[0]

然后在模板中:

{{ fruits|lineup }}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM