fruits
がリスト['apples', 'oranges', 'pears']
の場合、
Djangoテンプレートタグを使用して「リンゴ、オレンジ、ナシ」を作成する簡単な方法はありますか?
ループと{% if counter.last %}
ステートメントを使用してこれを行うことは難しいことではないことを知っていますが、これを繰り返し使用するため、カスタムの書き方を学ぶ必要があると思います タグ フィルターを使用します。ホイールが既に作成されている場合は、ホイールを再発明したくありません。
拡張機能として、 Oxford Comma (つまり、「リンゴ、オレンジ、梨」を返す)をドロップしようとする試みは、さらに厄介です。
これが私の問題を解決するために書いたフィルターです(オックスフォードコンマは含まれていません)
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 }}
最初の選択:既存の結合テンプレートタグを使用します。
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#join
ここに彼らの例があります
{{ value|join:" // " }}
2番目の選択:ビューで実行します。
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 %}
カスタムtagではなく、カスタムDjango templatingfilter)をお勧めします-フィルタは便利でシンプル(適切な場合、ここのように){{ fruits | joinby:", " }}
は、目的のために欲しいもののように見えます...カスタムjoinby
フィルターで:
def joinby(value, arg):
return arg.join(value)
あなたが見るように、それはシンプルそのものです!
Djangoテンプレートで、これは各果物の後にコンマを確立するために必要なことです。コンマは最後の果物に到達すると停止します。
{% if not forloop.last %}, {% endif %}
「。」が必要な場合Michael Matthew Toomimの答えの最後に、次を使用します。
{% if not forloop.last %}{% ifequal forloop.revcounter 2 %} and {% else %}, {% endifequal %}{% else %}{% endif %}{% if forloop.last %}.{% endif %}
ここでの答えはすべて、次の1つ以上に失敗します。
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')
そして今、コード。はい、少し面倒になりますが、あなたはそれを見ることができますdoes n't負のインデックスを使用します:
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 }}
コンテキストデータとしてテンプレートに送信する前に、単に', '.join(['apples', 'oranges', 'pears'])
を使用します。
更新:
data = ['apples', 'oranges', 'pears']
print(', '.join(data[0:-1]) + ' and ' + data[-1])
apples, oranges and pears
出力。
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 %}
ループを使用する必要があります。
ワンライナーが好きな場合:
@register.filter
def lineup(ls): return ', '.join(ls[:-1])+' and '+ls[-1] if len(ls)>1 else ls[0]
そしてテンプレートで:
{{ fruits|lineup }}