понедельник, 11 апреля 2011 г.

Django шаблоны. Разбиение списка.

Я недавно начал изучать Django и столкнулся с такой проблемой -- в шаблон передается список, а там то уже его надо разбить на две колонки. Представляю вам решение -- расширить набор тегов с помощью сниппетов (Django snippets).

Представленный сниппет разбивает список на n подсписков.

Тэг: {% list_to_columns ваш_список as новый_список колличество_колонок %}

Вам необязательно знать точное колличество эллементов в списке, а тлолько колличество коллонок на которые надо его разбить. Например у вас есть список:

monty = ['Eric', 'Graham', 'John', 'Michael', 'Terry', 'Terry']

Чтоб разбить его на три подсписка надо прописать:

{% list_to_columns monty as full_monty 3 %}

В результате получится новый список full_monty, содержащий три элемента:

['Eric', 'Graham']
['John', 'Michael']
['Terry', 'Terry']

Пример использования в шаблоне:

{% load list_to_columns %}
{% list_to_columns people as list 3 %}
{% for l in list %}
    (cycle through your div and ul code)
    {%for p in l %}
        (cycle through your list items)
    {% endfor %}
(end ul and div tags)
{% endfor %}

Чтобы заставить сниппет работать нужно сохранить файл list_to_columns.py  в директории templatetags вашего приложения. Т.е. если ваш проект называется mysite, а внутри него вы создали приложение myapp код сниппета надо разместить в папке mysite/myapp/templatetags/ . Также в этой папке должен находится пустой файл __init__.py .

Файл list_to_columns.py:

"""Splits query results list into multiple sublists for template display."""


from django.template import Library, Node


register = Library()


class SplitListNode(Node):
    def __init__(self, results, cols, new_results):
        self.results, self.cols, self.new_results = results, cols, new_results


    def split_seq(self, results, cols=2):
        start = 0
        for i in xrange(cols):
            stop = start + len(results[i::cols])
            yield results[start:stop]
            start = stop


    def render(self, context):
        context[self.new_results] = self.split_seq(context[self.results], int(self.cols))
        return ''


def list_to_columns(parser, token):
    """Parse template tag: {% list_to_colums results as new_results 2 %}"""
    bits = token.contents.split()
    if len(bits) != 5:
        raise TemplateSyntaxError, "list_to_columns results as new_results 2"
    if bits[2] != 'as':
        raise TemplateSyntaxError, "second argument to the list_to_columns tag must be 'as'"
    return SplitListNode(bits[1], bits[4], bits[3])


list_to_columns = register.tag(list_to_columns)


1 комментарий: