Django şablonlarındaki döngü için sayısal


261

forDjango şablonuna nasıl sayısal bir döngü yazarım ? Demek istediğim

for i = 1 to n

Yanıtlar:


392

Özel etiketleri ve ek bağlamı olmayan küçük durumlar için güzel çalışan basit bir teknik kullandım. Bazen bu işe yarar

{% for i in '0123456789'|make_list %}
    {{ forloop.counter }}
{% endfor %}

9
FWIW, 012 == 12, bu yüzden sadece 1 ve 2 üzerinde döngü yapacak
jason

22
{'0123456789' içindeki i için%% | make_list%} 10'un tümünü yineleyecek, 0 atlamayacak.
Rick

7
'Rjust' ile keyfi uzunluktaki bir dizi oluşturun{% for i in "x"|rjust:"100" %}
Aaron

27
3. kez, bu cevap KÖTÜ . Bunu KULLANMAYIN. Bir şablon etiketi kullanın ve doğru şekilde yapın. Bir cevabı söylemenin ne kadar kötü olduğunu, bir yorumu silmek için yeterli neden olduğunu göremiyorum.
Rebs

6
@Rebs Bu kadar kötü olan ne? Tabii ki hacky, ama bir şablonda küçük bir aralıkta bir kez döngü yapmanız gerektiğinden şablon etiketi eklemek de harika bir çözüm değil.
tobltobs

114
{% with ''|center:n as range %}
{% for _ in range %}
    {{ forloop.counter }}
{% endfor %}
{% endwith %}

9
Mükemmel cevap. Merkezi, daha sonra döngü içinde olan bir n boşluk dizesi oluşturduğu için çalışır. Daha sonra her boşluk karakteri yoksayılır, ancak aralıktaki geçerli değer forloop.counter (veya forloop.counter0) içinde bulunabilir. Bkz. Docs.djangoproject.com/en/dev/ref/templates/builtins/#center
isedwards

2
Mükemmel cevap! Yeni bir filtre oluşturmak zorunda değildi.
Miguel Ike

Görünümde hiçbir şey yapmanıza gerek yok. Mükemmel kesmek
Mohammed Shareef C

106

Ne yazık ki, bu Django şablon dilinde desteklenmiyor . Orada bir olan çift arasında önerileri , ama onlar biraz karmaşık görünüyor. Ben sadece bağlamda bir değişken koymak istiyorum:

...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...

ve şablonda:

{% for i in range %}
     ...
{% endfor %}

13
Django yazarlarının şablonlarda düz python'a izin vermemek için sahip oldukları motivasyonlar, mükemmel bir harika olan (python! ) zaten orada!
Bogatyr

2
@Bogatyr İstediğiniz buysa, Jinja2'yi
tghw

78

Bu konuda benim almak, en güzel olduğunu düşünüyorum. Şablon etiketleri dizininde bir my_filters.py saklıyorum.

@register.filter(name='times') 
def times(number):
    return range(number)

Ve şöyle kullanırsınız:

{% load my_filters %}
{% for i in 15|times %}
    <li>Item</li>
{% endfor %}

1
Bence bu doğru bir çözüm. range(1, 16)0'dan değil, 1'den başlayan numaraları almak için yapın .
chhantyal

Ayrıca templatetags dizininde boş bir dosya _ init _.py oluşturun. Ayrıca bu satırı my_filters.py'nin üstüne ekleyin from django.template import Library;register = Library()
Ajeeb.KP

İkinci bir filtre parametresi ekleyin ve tam aralık işlevini python'a entegre edin. @register.filter(name='range') def filter_range(start, end): return range(start, end)Sonra olarak kullanılır {% for i in 1|range:6 %}{% endfor %}. Aşağıdaki tam cevabı görün ....
Paul Kenjora

Ben (biçimlendirme mazur) biraz bu değişmiş: try: return range(number) except: return []. Bu şekilde hiçbir zaman hata oluşturmaz ve boş bir dizi döndürür (çoğu şablon işlevinin çalışma biçimine benzer).
Tim Tisdall


41

Bir ciltleme geçebilirsiniz

{'n' : range(n) }

şablona gidin, sonra yapın

{% for i in n %}
...
{% endfor %}

0 tabanlı davranış (0, 1, ... n-1) elde edeceğinizi unutmayın.

(Python3 uyumluluğu için güncellendi)


1
range(n)Python 3'te kullanın , doğru hatırlıyorsam, xrange üzerinde kullanımdan kaldırıldı
Felício

Gerçekten evet. Ve bu, bir uygulamayı Python3'e geçirme şansı bulduğum iki kod satırından biriydi.
Dave W. Smith

9

Kendi başınıza değil n, daha ziyade range(n)[0'dan n-1'e kadar tamsayıların listesi], görünümünüzden şablonunuza ve sonrakinde {% for i in therange %}(normal 0 yerine 1 tabanlı olarak ısrar ediyorsanız) forloop.counterdöngüsünün gövdesinde kullanabileceğiniz temelli dizin ;-).


9

Başka Sadece örtmek herkes bu soruya rastlar ... Sana bir oluşturmanıza olanak sağlayan bir şablon etiket oluşturdunuz range(...): http://www.djangosnippets.org/snippets/1926/

'Range' yerleşimi ile aynı argümanları kabul eder ve aşağıdakileri içeren bir liste oluşturur
'aralık' sonucu.

Sözdizimi:
    {% mkrange [start,] stop [, step], bağlam_adı%}

Örneğin:
    {% mkrange 5 10 2, bazı_aralık% olarak}
    {some_range% içindeki i için%%}
      {{i}}: Tekrarlamak istediğim bir şey \ n
    {% endfor%}

üretir:
    5: Tekrarlamak istediğim bir şey 
    7: Tekrarlamak istediğim bir şey 
    9: Tekrarlamak istediğim bir şey


1
-1, Alex Pi'nin değişken argümanlarına destek veren snippet'in lehine.
m000

9

Bu soru üzerinde çok çalıştım ve burada en iyi cevabı buluyorum: ( django şablonlarında 7 kez döngüden )

İdx'e bile erişebilirsiniz!

views.py:

context['loop_times'] = range(1, 8)

html:

{% for i in loop_times %}
        <option value={{ i }}>{{ i }}</option>
{% endfor %}

9

Geçebilirsin :

{'n': aralık (n)}

Şablonu kullanmak için:

{% n içinde i için%%} ... {% endfor%}


okunabilir ve basit, kodu koruyan bir sonraki adam iseniz ne olduğunu anlamak kolay
rossdavidh

7

" Dilim "Şablonda " , şöyle bir örnek:

views.py içinde

contexts = {
    'ALL_STORES': Store.objects.all(),
}

return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))

store_list.html dosyasında:

<ul>
{% for store in ALL_STORES|slice:":10" %}
    <li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>

1
OP'nin aradığı şey buysa emin değilim, ama tam da aradığım şey buydu. =)
GChorn

7

Bu yöntem standart range([start,] stop[, step])işlevin tüm işlevlerini destekler

<app>/templatetags/range.py

from django import template

register = template.Library()


@register.filter(name='range')
def _range(_min, args=None):
    _max, _step = None, None
    if args:
        if not isinstance(args, int):
            _max, _step = map(int, args.split(','))
        else:
            _max = args
    args = filter(None, (_min, _max, _step))
    return range(*args)

Kullanımı:

{% load range %}

<p>stop 5
{% for value in 5|range %}
{{ value }}
{% endfor %}
</p>

<p>start 5 stop 10
{% for value in 5|range:10 %}
{{ value }}
{% endfor %}
</p>

<p>start 5 stop 10 step 2
{% for value in 5|range:"10,2" %}
{{ value }}
{% endfor %}
</p>

Çıktı

<p>stop 5
0 1 2 3 4
</p>

<p>start 5 stop 10
5 6 7 8 9
</p>

<p>start 5 stop 10 step 2
5 7 9
</p>

çözümünüz çalışmıyor for value in 0|range:"10,2". Kodunuzu aşağıdaki gibi değiştirmeniz gerekir:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Bedilbek

@Bedilbek bu kod standart python aralığını taklit eder. açık bir adım parametresi olmadan negatif aralıkları desteklemese bile. >>> liste (aralık (10,2)) [] >>> liste (aralık (10,2, -1)) [10, 9, 8, 7, 6, 5, 4, 3]
Rebs

5

Popüler yanıtı biraz daha ileriye götürüyorum ve daha sağlam hale getiriyorum. Bu, herhangi bir başlangıç ​​noktası belirtmenize izin verir, örneğin 0 veya 1. Ayrıca, örneğin liste uzunlukları ile doğrudan kullanılabilmesi için sonun daha az olduğu python aralık özelliğini de kullanır.

@register.filter(name='range')
def filter_range(start, end):
  return range(start, end)

Ardından, şablonunuza yukarıdaki şablon etiketi dosyasını ekleyin ve aşağıdakileri kullanın:

{% for c in 1|range:6 %}
{{ c }}
{% endfor %}

Şimdi sadece 0-6 yerine 1-6 veya sert kodlama yapabilirsiniz. Bir adım eklemek bir şablon etiketi gerektirir; bu, daha fazla kullanım durumunu kapsaması için ileriye doğru bir adımdır.


Bu @ guillermo-siliceo-trueba cevabının bir uzantısıdır.
Paul Kenjora

5

Bu aslında bir rangeişlev gerektirir . Bunun için bir Django özellik bileti ( https://code.djangoproject.com/ticket/13088 ) oluşturuldu, ancak aşağıdaki yorumla "düzeltilmeyecek" şeklinde kapatıldı.

Bu fikir hakkındaki izlenimim, şablonda programlamaya yol açmaya çalıştığıdır. Oluşturulması gereken seçeneklerin bir listeniz varsa, bunlar şablonda değil görünümde hesaplanmalıdır. Bu bir değer aralığı kadar basitse, öyle olsun.

İyi bir noktaya sahipler - Şablonların manzaranın çok basit bir temsili olması gerekiyor. Görünümde gerekli olan sınırlı verileri oluşturmanız ve bağlam içindeki şablona iletmeniz gerekir.


6
Görünüm veriler için, şablon sunum için olmalıdır. Görünüm, şablonun içeriği, özellikle aralıklar hakkında bilgi gerektirmemelidir. Django'nun bu özellik taleplerini göz ardı etme nedeni tamamen saçmalık.
Rebs

3

Kullanabilirsiniz: {% with ''|center: i as range %}


1
Bunun nasıl çalıştığına dair bir örnek / açıklama verebilir misiniz?
Rebs

1

Basit bir cevap arayanlar için, sadece bir miktar değer göstermesi gerekenler için, örneğin 100 mesajdan 3'ü sadece {% for post in posts|slice:"3" %}normal şekilde ekleyin ve döngüye sokun ve sadece 3 mesaj ekleyelim .


0

Sayı bir modelden geliyorsa, bunu modele hoş bir yama olarak buldum:

def iterableQuantity(self):
    return range(self.quantity)

2
Neden oy kullanacağınızdan emin değilsiniz, bu geçerli bir cevap. Yukarıda verdiğim gibi uygun bir filtre uygulamakla karşılaştırıldığında bu çözümü sevmiyorum. DB modelleri zayıf tutulmalıdır. Ama yine de çoğunluğun kabul ettiği cevaptan daha iyi.
Rebs

Bilmiyorum bile ...
Alper

9 yıl çok geç kaldım ama seni fethettik, endişelenme bile.
Sahil

-5
{% for i in range(10) %}
   {{ i }}

{% endfor %}

Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
xiawi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.