2009-05-10 28 views
5

Tôi gặp vấn đề với Django. Tôi có một tập hợp các đối tượng mà Im lặp qua trong một mẫu như bình thường. Tuy nhiên, tôi cần phải nhóm các mục trong số ba. Cách bố trí của trang đi như thế này:Các mẫu Django: Các mục nhóm trong Threes

Sơn 1 - Tranh 2 - Tranh 3

MÔ TẢ 1
MÔ TẢ 2
MÔ TẢ 3

Tranh 4 - Vẽ tranh - 5 Tranh 6

MÔ TẢ 4
MÔ TẢ 5
DES C R I P T I O N 6

vv vv

tôi không thể hình dung ra khá tập tốt nhất của thẻ Django để làm điều này thực sự. Nó có vẻ hơi phức tạp. câu lệnh {% cycle%} không hoàn toàn hữu ích.

Trừ khi tất nhiên, tôi thực hiện một số tập lệnh java hack và loại bỏ Django trong số này? Phải có một cách khác để nói "Đặt tất cả các div mô tả sau cái khác" hoặc tương tự. Không chắc chắn cách tốt nhất để chơi với thứ tự này. Có suy nghĩ gì không? Chúc mừng.

Trả lời

5

Bất cứ khi nào bạn thấy mình đang thử mã phức tạp bên trong các mẫu, nó thường là dấu hiệu tốt cho thấy nó nên được di chuyển ở nơi khác.Một trong những giải pháp thay thế đã được đề xuất, đó là để di chuyển mã vào chức năng xem của bạn.

Giải pháp khác là để hiển thị chức năng thông qua thẻ mẫu mới. Một trong những lý do bạn chọn giải pháp này trên giải pháp xem là bạn sẽ có thể dễ dàng sử dụng lại mã cho các trang được phân phối với các chế độ xem khác nhau.

class GroupPaintingsNode(template.Node): 
    def __init__(self, num, varname): 
     self.num, self.varname = int(num), varname 

    def render(self, context): 
     paintings = Painting.objects.all # do your fetching/filtering here.. 
     l = [[] for i in range(len(paintings))] 
     i = 0 
     while i < len(paintings): 
      l[i].append([p.title for p in paintings[i:i+self.num]]) 
      l[i].append([p.desc for p in paintings[i:i+self.num]]) 
      i += self.num 
     context[self.varname] = l 
     return '' 

def group_paintings(parser, token): 
    tokens = token.contents.split() 
    if len(tokens) != 4: 
     raise template.TemplateSyntaxError, "'%s' tag requires three arguments" % tokens[0] 
    if tokens[2] != 'as': 
     raise template.TemplateSyntaxError, "Second argument to '%s' tag must be 'as'" % tokens[0] 
    return GroupPaintingsNode(tokens[1], tokens[3]) 
group_paintings = register.tag(group_paintings) 

Trong mẫu mã bạn sẽ sử dụng nó như thế này:

{% group_paintings 3 as paintings %} 
{% for p in paintings %} 
    {% for title in p.0 %} {{ title }} {% endfor %}<br> 
    {% for desc in p.1 %} {{ desc }} {% endfor %} 
{% endfor %} 
+0

Tôi nghĩ rằng đây có vẻ tốt nhất như một mẫu thẻ là nơi đẹp nhất cho chức năng này để đi như phản đối một cái nhìn khó xử hơn. Rất nhiều danh sách ở đó nhưng tôi nhận được nó :) Một số giải pháp thanh lịch ở đó! Cảm ơn :) – Oni

5

thế nào là về điều gì đó xung quanh những dòng này:

{% for p in paintingss %} 
    <div class="painting">whatever</div> 
    {% if forloop.counter|divisibleby:"3" %} 
     <br> 
    {% endif %} 
{% endfor %} 

này sẽ làm bạn tốt?

3

Yuval nằm trên dòng bên phải, nhưng có vẻ như bạn muốn lặp qua danh sách tranh hai lần: một lần để hiển thị tên (ba dòng trên mỗi dòng) và một lần cho mô tả. Điều này hoàn toàn không dễ dàng đạt được trong ngôn ngữ mẫu.

Tôi khuyên bạn nên xem liệu bạn có thể làm điều gì đó với một số CSS hay không. Bạn có thể chỉ định một lớp cho tên và/hoặc div mô tả sao cho tất cả các tên được thả nổi cùng nhau và các mô tả hiển thị dưới dạng các khối bên dưới. Tuy nhiên, vẫn còn khó khăn.

Ngoài ra, bạn có thể xử lý trước danh sách trong chế độ xem của mình, để bạn tách biệt tên và mô tả thành các nhóm ba. Bạn muốn kết thúc với cấu trúc này:

[ 
    [name1, name2, name3], 
    [description1, description2, description3], 
    [name4, name5, name6], 
    [description4, description5, description6], 
    ... 
] 

Vì vậy, bạn có thể cố gắng làm điều này:

painting_list = [] 
counter = 0 
while counter < len(paintings): 
    painting_list.append([p.name for p in paintings[counter:counter+3]) 
    painting_list.append([p.description for p in paintings[counter:counter+3]) 
    counter += 3 

và sau đó trong mẫu của bạn:

{% for group in painting_list %} 
    <div class="names">{% for name in group.0 %}{{ name }} {% endfor %}</div> 

    <ul class="descriptions"> 
     {% for description in group.1 %} 
     <li>{{ description }}</li> 
     {% endfor %} 
    </ul> 
{% endfor %} 
2

Tôi chắc chắn bỏ phiếu cho việc tạo cấu trúc theo quan điểm của bạn và chuyển nó vào mẫu của bạn dưới dạng đúng.

Nếu bạn thấy mình đang gặp khó khăn với logic mẫu thì đó là dấu hiệu bạn nên thực hiện nhiều công việc trong chế độ xem của mình. (điều này cũng dạy tôi rằng một chút logic xem của tôi cần phải được đẩy trở lại vào các mô hình của tôi ...)

0
{% for painting in painting_list %} 
    <div class="painting">{{ painting }}</div> 
    {% if forloop.counter|divisibleby:"3" %} 
     <br> 
     {{ description_list.forloop.counter0-2 }} 
     {{ description_list.forloop.counter0-1 }} 
     {{ description_list.forloop.counter0 }} 
    {% endif %} 
{% endfor %} 

chỉ để bạn biết mã này sẽ không làm việc, nhưng một cái gì đó như thế này là những gì bạn muốn.

Có thể bạn có thể tạo ra templatetag của riêng mình để truy cập đối tượng thứ n trong danh sách đối tượng.

5

Bạn có thể sử dụng một bộ lọc đơn giản cho việc này:

import itertools 

from django import template 

register = template.Library() 

@register.filter 
def chunks(value, chunk_length): 
    """ 
    Breaks a list up into a list of lists of size <chunk_length> 
    """ 
    clen = int(chunk_length) 
    i = iter(value) 
    while True: 
     chunk = list(itertools.islice(i, clen)) 
     if chunk: 
      yield chunk 
     else: 
      break 

Sau đó, bên trong mẫu của bạn:

{% for chunk in paintings|chunks:3 %} 
    <div class="row"> 
    {% for painting in chunk %} 
     <div>{{ painting }}</div> 
    {% endfor %} 
    </div> 
{% endfor %} 
Các vấn đề liên quan