ตัวเลขสำหรับลูปในแม่แบบ Django


261

ฉันจะเขียนforลูปตัวเลขในเทมเพลต Django ได้อย่างไร ฉันหมายถึงสิ่งที่ชอบ

for i = 1 to n

คำตอบ:


392

ฉันใช้เทคนิคง่าย ๆ ที่ทำงานได้ดีสำหรับกรณีเล็ก ๆ โดยไม่มีแท็กพิเศษและไม่มีบริบทเพิ่มเติม บางครั้งสิ่งนี้มีประโยชน์

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

9
FWIW, 012 == 12 ดังนั้นมันจะวนซ้ำ 1 และ 2 เท่านั้น
jason

22
{% สำหรับฉันใน '0123456789' | make_list%} เพื่อวนซ้ำทั้ง 10 รายการไม่ข้าม 0
ริ

7
สร้างสตริงที่มีความยาวตามอำเภอใจด้วย 'rjust'{% for i in "x"|rjust:"100" %}
Aaron

27
เป็นครั้งที่ 3 ที่คำตอบนี้คือไม่ดี ห้ามใช้สิ่งนี้ ใช้เทมเพลตแท็กและทำอย่างถูกต้อง ฉันล้มเหลวในการดูว่าคำตอบไม่ดีมีเหตุผลเพียงพอที่จะลบความคิดเห็น
Rebs

6
@Rebs เลวร้ายอะไรกับเรื่องนี้? แน่นอนว่ามันเป็นการแฮ็ก แต่การเพิ่มเทมเพลตแท็กเพียงเพราะคุณต้องวนซ้ำช่วงเล็ก ๆ เป็นครั้งเดียวในโครงการนั่นก็ไม่ใช่วิธีการแก้ปัญหาที่ยอดเยี่ยม
tobltobs

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

9
คำตอบที่ดี ทำงานได้เนื่องจากศูนย์สร้างสตริงของช่องว่าง n ที่วนลูปแล้ว ถ่านอวกาศแต่ละตัวจะถูกละเว้น แต่ค่าปัจจุบันในช่วงสามารถพบได้จาก forloop.counter (หรือ forloop.counter0) ดูdocs.djangoproject.com/en/dev/ref/templates/builtins/#center
isedwards

2
คำตอบที่ดี! ไม่จำเป็นต้องสร้างตัวกรองใหม่
Miguel Ike

ไม่จำเป็นต้องทำอะไรในมุมมอง แฮ็คที่ยอดเยี่ยม
โมฮัมเหม็ด Shareef C

106

น่าเสียดายที่ไม่รองรับภาษาเทมเพลต Django มีความเป็นคู่ ของข้อเสนอแนะแต่พวกเขาดูเหมือนซับซ้อนน้อย ฉันจะใส่ตัวแปรในบริบท:

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

และในเทมเพลต:

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

13
แรงบันดาลใจของผู้เขียน Django ที่มีต่อการอนุญาตให้ใช้งูหลามธรรมดาในเทมเพลตดูเหมือนไม่มีประโยชน์และไม่สมเหตุผลเมื่อเทียบกับความเจ็บปวดและเวลาที่เสียไปซึ่งเกี่ยวข้องกับการหลีกเลี่ยงไม่ต้องพูดถึงมัน ) มีอยู่แล้ว!
Bogatyr

2
@Bogatyr ถ้านั่นคือสิ่งที่คุณต้องการเพียงแค่ใช้ Jinja2: docs.djangoproject.com/en/1.9/topics/templates/...
tghw

78

เรื่องของฉันเกี่ยวกับเรื่องนี้ฉันคิดว่ามันอร่อยที่สุด ฉันเก็บ my_filters.py ไว้ในไดเรกทอรี templatetags

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

และคุณจะใช้สิ่งนี้:

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

1
ฉันคิดว่านี่เป็นทางออกที่ถูกต้อง ทำอย่างไรrange(1, 16)เพื่อให้ได้ตัวเลขตั้งแต่วันที่ 1 ไม่ใช่ 0.
chhantyal

สร้างไฟล์ว่าง _ init _.py ในไดเรกทอรี templatetags ด้วย เพิ่มบรรทัดเหล่านี้ไปยังด้านบนของ my_filters.py from django.template import Library;register = Library()
Ajeeb.KP

เพิ่มพารามิเตอร์ตัวกรองตัวที่สองและคุณจะได้รับฟังก์ชั่นเต็มรูปแบบที่สร้างไว้ในหลาม จากนั้นได้รับการใช้เป็น@register.filter(name='range') def filter_range(start, end): return range(start, end) {% for i in 1|range:6 %}{% endfor %}ดูคำตอบแบบเต็มด้านล่าง ....
Paul Kenjora

ฉันเปลี่ยนแปลงนี้เล็กน้อย try: return range(number) except: return [](ข้ออ้างการจัดรูปแบบ): วิธีนั้นจะไม่ทำให้เกิดข้อผิดพลาดและส่งกลับอาร์เรย์ที่ว่างเปล่า (คล้ายกับการทำงานของแม่แบบส่วนใหญ่)
Tim Tisdall


41

คุณสามารถผ่านการผูกพัน

{'n' : range(n) }

ไปที่เทมเพลตจากนั้นทำ

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

โปรดทราบว่าคุณจะได้รับพฤติกรรมตาม 0 (0, 1, ... n-1)

(อัปเดตเพื่อรองรับ Python3)


1
ใช้range(n)ใน python 3 ถ้าฉันจำได้ถูกต้อง xrange ก็เลิกใช้แล้ว
Felício

ใช่แน่นอน และนั่นเป็นหนึ่งในสองบรรทัดของโค้ดที่ฉันต้องมีโอกาสในการเปลี่ยนแอพเป็น Python3
Dave W. Smith เมื่อ

9

คุณไม่ผ่านnตัวเอง แต่range(n)[รายชื่อของจำนวนเต็มจาก 0 ถึง n-1 รวม] จากมุมมองของคุณแม่แบบของคุณและในสมัยที่คุณทำ{% for i in therange %}(ถ้าคุณอย่างแน่นอนยืนยันใน 1 ตามมากกว่าปกติ 0 ดัชนีพื้นฐานที่คุณสามารถใช้forloop.counterในร่างกายของวง ;-)


9

แค่ใส่เคสคนอื่นเจอคำถามนี้…ฉันได้สร้างเทมเพลตแท็กที่ให้คุณสร้างrange(...): http://www.djangosnippets.org/snippets/1926/

ยอมรับอาร์กิวเมนต์เช่นเดียวกับ builtin 'range' และสร้างรายการที่มี
ผลลัพธ์ของ 'ช่วง'

ไวยากรณ์:
    {% mkrange [เริ่ม,] หยุด [, ขั้นตอน] เป็น context_name%}

ตัวอย่างเช่น:
    {% mkrange 5 10 2 เป็น some_range%}
    {% สำหรับฉันใน some_range%}
      {{i}}: บางสิ่งที่ฉันต้องการทำซ้ำ \ n
    {% endfor%}

ผลิต:
    5: บางสิ่งที่ฉันต้องการทำซ้ำ 
    7: บางสิ่งที่ฉันต้องการทำซ้ำ 
    9: บางสิ่งที่ฉันต้องการทำซ้ำ


1
-1 สนับสนุนตัวอย่างของ Alex Pi ซึ่งเพิ่มการสนับสนุนการขัดแย้งตัวแปร
m000

9

ฉันพยายามอย่างหนักกับคำถามนี้และฉันพบคำตอบที่ดีที่สุดที่นี่: (จากการวนรอบ 7 ครั้งในเทมเพลต django )

คุณสามารถเข้าถึง idx ได้!

views.py:

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

HTML:

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

9

คุณสามารถผ่าน:

{'n': range (n)}

วิธีใช้เทมเพลต:

{% สำหรับฉันใน n%} ... {% endfor%}


อ่านง่ายเข้าใจง่ายว่าเกิดอะไรขึ้นถ้าคุณเป็นคนต่อไปที่รักษารหัสไว้
rossdavidh

7

คุณควรใช้ " ชิ้น " ในแม่แบบเช่นนี้:

ใน views.py

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

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

ใน store_list.html:

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

1
ไม่แน่ใจว่านี่คือสิ่งที่ OP ต้องการหรือไม่ แต่เป็นสิ่งที่ฉันต้องการ =)
GChorn

7

วิธีนี้รองรับฟังก์ชั่นทั้งหมดของrange([start,] stop[, step])ฟังก์ชั่นมาตรฐาน

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

การใช้งาน:

{% 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>

เอาท์พุต

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

for value in 0|range:"10,2"วิธีการแก้ปัญหาของคุณไม่ทำงานบน คุณต้องเปลี่ยนรหัสดังนี้:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Bedilbek

@Bedilbek รหัสนี้เลียนแบบช่วงไพ ธ อนมาตรฐาน แม้ว่าจะไม่สนับสนุนช่วงลบโดยไม่มีพารามิเตอร์ขั้นตอนที่ชัดเจน >>> รายการ (ช่วง (10,2)) [] >>> รายการ (ช่วง (10,2, -1)) [10, 9, 8, 7, 6, 6, 5, 4, 3]
Rebs

5

ฉันแค่ใช้คำตอบที่ได้รับความนิยมเพิ่มขึ้นอีกเล็กน้อยและทำให้แข็งแกร่งขึ้น สิ่งนี้ช่วยให้คุณระบุจุดเริ่มต้นใด ๆ ได้เช่น 0 หรือ 1 นอกจากนี้ยังใช้ฟีเจอร์พิสัยของไพ ธ อนที่ส่วนท้ายมีค่าน้อยกว่าจึงสามารถใช้กับความยาวของรายการได้โดยตรง

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

จากนั้นในเทมเพลตของคุณให้รวมไฟล์แท็กเทมเพลตด้านบนและใช้สิ่งต่อไปนี้:

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

ตอนนี้คุณสามารถทำได้ 1-6 แทนที่จะเป็นเพียง 0-6 หรือการเข้ารหัสอย่างหนัก การเพิ่มขั้นตอนจะต้องใช้แท็กเทมเพลตซึ่งจะครอบคลุมการใช้งานมากขึ้นดังนั้นจึงเป็นขั้นตอนต่อไป


นี่เป็นส่วนขยายของคำตอบ @ guillermo-siliceo-trueba
Paul Kenjora

5

สิ่งนี้จำเป็นต้องมีrangeฟังก์ชั่น ตั๋วฟีเจอร์ Django ถูกยกขึ้น ( https://code.djangoproject.com/ticket/13088 ) สำหรับสิ่งนี้ แต่ปิดเนื่องจาก "ไม่แก้ไข" พร้อมกับความคิดเห็นต่อไปนี้

ความประทับใจของฉันเกี่ยวกับความคิดนี้คือมันกำลังพยายามนำไปสู่การเขียนโปรแกรมในเทมเพลต หากคุณมีรายการของตัวเลือกที่จำเป็นต้องแสดงผลพวกเขาควรจะคำนวณในมุมมองไม่ใช่ในแม่แบบ ถ้ามันง่ายเหมือนช่วงของค่าลองดูสิ

พวกเขามีจุดดี - เทมเพลตควรจะเป็นมุมมองที่ง่ายมาก คุณควรสร้างข้อมูลที่จำเป็นอย่าง จำกัด ในมุมมองและส่งต่อไปยังเทมเพลตในบริบท


6
มุมมองควรเป็นข้อมูลเทมเพลตควรใช้สำหรับงานนำเสนอ มุมมองไม่ควรต้องการความรู้เกี่ยวกับเนื้อหาของเทมเพลตโดยเฉพาะช่วง เหตุผลของ Django ที่เพิกเฉยต่อคำขอคุณสมบัติเหล่านี้เป็นสิ่งที่ไร้ค่าที่สุด
Rebs

3

คุณสามารถใช้ได้: {% with ''|center: i as range %}


1
คุณสามารถให้ตัวอย่าง / คำอธิบายว่ามันทำงานอย่างไร?
Rebs

1

สำหรับผู้ที่ต้องการคำตอบง่ายๆเพียงแค่ต้องการแสดงค่าจำนวนหนึ่งให้พูดว่า 3 จาก 100 โพสต์ตัวอย่างเพียงแค่เพิ่ม{% for post in posts|slice:"3" %}และวนซ้ำตามปกติและจะเพิ่มเพียง 3 โพสต์


0

หากตัวเลขมาจากแบบจำลองฉันพบว่านี่เป็น patch ที่ดีสำหรับรุ่น:

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

2
ไม่แน่ใจว่าทำไมคุณถึงลงคะแนนมันเป็นคำตอบที่ถูกต้อง ฉันไม่ชอบวิธีนี้เทียบกับการใช้ตัวกรองที่เหมาะสมตามที่ฉันได้ให้ไว้ข้างต้น ควรเก็บตัวแบบลีนไว้ แต่ก็ยังดีกว่าคำตอบที่คนส่วนใหญ่ยอมรับ
Rebs

ฉันไม่ได้รู้ว่า ...
Alper

ฉันอายุเกิน 9 ปีแล้ว แต่ฉันก็สนับสนุนคุณให้สูงขึ้นอย่ากังวลไปเลย
Sahil

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

{% endfor %}

ในขณะที่รหัสนี้อาจตอบคำถาม แต่มีบริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีการที่รหัสนี้ตอบคำถามช่วยปรับปรุงมูลค่าระยะยาว
xiawi
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.