Câu trả lời:
Tôi đã sử dụng một kỹ thuật đơn giản hoạt động độc đáo cho các trường hợp nhỏ không có thẻ đặc biệt và không có ngữ cảnh bổ sung. Đôi khi điều này có ích
{% for i in '0123456789'|make_list %}
{{ forloop.counter }}
{% endfor %}
{% for i in "x"|rjust:"100" %}
{% with ''|center:n as range %}
{% for _ in range %}
{{ forloop.counter }}
{% endfor %}
{% endwith %}
Thật không may, điều đó không được hỗ trợ trong ngôn ngữ mẫu Django. Có một cặp vợ chồng của lời đề nghị , nhưng họ dường như một chút phức tạp. Tôi sẽ chỉ đặt một biến trong bối cảnh:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
và trong mẫu:
{% for i in range %}
...
{% endfor %}
Tôi nghĩ về vấn đề này, tôi nghĩ là tốt nhất. Tôi giữ một my_filters.py trên thư mục templatetags.
@register.filter(name='times')
def times(number):
return range(number)
Và bạn sẽ sử dụng như thế này:
{% load my_filters %}
{% for i in 15|times %}
<li>Item</li>
{% endfor %}
range(1, 16)
để có được số bắt đầu từ 1, không phải 0.
from django.template import Library;register = Library()
@register.filter(name='range') def filter_range(start, end): return range(start, end)
Sau đó được sử dụng như {% for i in 1|range:6 %}{% endfor %}
. Xem câu trả lời đầy đủ bên dưới ....
try: return range(number) except: return []
. Bằng cách đó, nó không bao giờ phát sinh lỗi và trả về một mảng trống (tương tự như cách mà hầu hết các hàm mẫu hoạt động).
Có lẽ như thế này?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
Bạn có thể vượt qua một ràng buộc của
{'n' : range(n) }
vào mẫu, sau đó làm
{% for i in n %}
...
{% endfor %}
Lưu ý rằng bạn sẽ có hành vi dựa trên 0 (0, 1, ... n-1).
(Cập nhật cho khả năng tương thích Python3)
range(n)
trong python 3, nếu tôi nhớ chính xác, xrange không được dùng nữa
Bạn không vượt qua n
chính nó, nhưng thay vào đó range(n)
[danh sách các số nguyên từ 0 đến n-1], từ chế độ xem của bạn đến mẫu của bạn và sau này bạn làm {% for i in therange %}
(nếu bạn hoàn toàn nhấn mạnh vào 1 dựa trên thay vì 0 thông thường chỉ số dựa trên bạn có thể sử dụng forloop.counter
trong cơ thể của vòng lặp ;-).
Chỉ cần bất cứ ai khác gặp phải câu hỏi này, tôi đã tạo một thẻ mẫu cho phép bạn tạo một range(...)
: http://www.djangosnippets.org/snippets/1926/
Chấp nhận các đối số tương tự như nội dung 'phạm vi' và tạo một danh sách chứa kết quả của 'phạm vi'. Cú pháp: {% mkrange [bắt đầu,] dừng [, bước] dưới dạng bối cảnh%} Ví dụ: {% mkrange 5 10 2 dưới dạng some_range%} {% cho tôi trong some_range%} {{i}}: Một cái gì đó tôi muốn lặp lại \ n {% kết thúc%} Sản xuất: 5: Một cái gì đó tôi muốn lặp lại 7: Một cái gì đó tôi muốn lặp lại 9: Một cái gì đó tôi muốn lặp lại
Tôi đã rất cố gắng cho câu hỏi này và tôi tìm thấy câu trả lời tốt nhất ở đây: (từ cách lặp 7 lần trong các mẫu django )
Bạn thậm chí có thể truy cập idx!
lượt xem:
context['loop_times'] = range(1, 8)
html:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
Bạn có thể vượt qua :
{'n': phạm vi (n)}
Để sử dụng mẫu:
{% cho tôi trong n%} ... {% endfor%}
Bạn nên sử dụng " lát " trong mẫu, một ví dụ như thế này:
trong lượt xem
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
trong store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
Phương pháp này hỗ trợ tất cả các chức năng của range([start,] stop[, step])
chức năng tiêu chuẩn
<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)
Sử dụng:
{% 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>
Đầu ra
<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"
. Bạn phải thay đổi mã của mình như sau:args = filter(lambda x: isinstance(x, int) and x >= 0, (_min, _max, _step))
Tôi chỉ lấy câu trả lời phổ biến hơn một chút và làm cho nó mạnh mẽ hơn. Điều này cho phép bạn chỉ định bất kỳ điểm bắt đầu, vì vậy 0 hoặc 1 chẳng hạn. Nó cũng sử dụng tính năng phạm vi của python trong đó phần cuối là một ít hơn để nó có thể được sử dụng trực tiếp với độ dài danh sách chẳng hạn.
@register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Sau đó, trong mẫu của bạn chỉ cần bao gồm tệp thẻ mẫu ở trên và sử dụng như sau:
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Bây giờ bạn có thể làm 1-6 thay vì chỉ 0-6 hoặc mã hóa cứng. Thêm một bước sẽ yêu cầu thẻ mẫu, điều này sẽ bao gồm nhiều trường hợp sử dụng hơn vì vậy đó là một bước tiến.
Điều này về cơ bản đòi hỏi một range
chức năng. Một vé tính năng Django đã được nâng lên ( https://code.djangoproject.com/ticket/13088 ) cho điều này nhưng đóng lại là "sẽ không sửa chữa" với nhận xét sau.
Ấn tượng của tôi về ý tưởng này là nó đang cố gắng dẫn đến lập trình trong mẫu. Nếu bạn có một danh sách các tùy chọn cần được hiển thị, chúng sẽ được tính toán trong dạng xem, không phải trong mẫu. Nếu điều đó đơn giản như một loạt các giá trị, thì nó cũng vậy.
Họ có một điểm tốt - Mẫu được cho là đại diện rất đơn giản của chế độ xem. Bạn nên tạo dữ liệu yêu cầu hạn chế trong chế độ xem và chuyển đến mẫu trong ngữ cảnh.
Đối với những người đang tìm kiếm câu trả lời đơn giản, chỉ cần hiển thị một lượng giá trị, giả sử 3 từ 100 bài viết, ví dụ chỉ cần thêm {% for post in posts|slice:"3" %}
và lặp nó bình thường và chỉ có 3 bài đăng sẽ được thêm vào.
Nếu số đến từ một mô hình, tôi thấy đây là một bản vá đẹp cho mô hình:
def iterableQuantity(self):
return range(self.quantity)
{% for i in range(10) %}
{{ i }}
{% endfor %}