Для примера реализуем тег pagination который будет получать какой-то список объектов и отдавать объект Paginator. Ситнаксис тэга будет такой:
{% pagination objects as pagination_objects %}.Итак код:
- def do_pagination(parser, token):
- bits = token.split_contents()
- if len(bits) != 5:
- raise TemplateSyntaxError('%r syntax is %s obj_list num as varname ' % (bits[0], bits[0]))
- if bits[3] != 'as':
- raise TemplateSyntaxError('%r required "as" beetwen arguments' % bits[0])
- obj_list = parser.compile_filter(bits[1])
- page_size = bits[2]
- return_name = bits[-1]
- return PaginationNode(obj_list, return_name, page_size)
Разберем по порядку:
- Метод do_pagination разбирает строку тэга, делает необходимые проверки и возвращает экземпляр класса PaginationNode
- bits - здесь содержится массив разобранной строки.
- if len(bits) != 5: ... тут идут проверки синтаксиса шаблона
- obj_list = parser.compile_filter(bits[1]) - вот здесь важный момент, в obj_list получаем переменную типа template.Variable при помощи метода compile_filter(), она нужна только затем чтобы потом вызвать у неё метод resolve(context) и получить саму переменную из контекста шаблона, об этом далее
Теперь реализуем класс PaginationNode который будет создавать в контексте шаблона столь необходимый пэйджинг.
- class PaginationNode(template.Node):
- def __init__(self, obj_list, return_name, page_size):
- self.obj_list = obj_list
- self.return_name = return_name
- self.page_size = page_size
- def render(self, context):
- actual_obj_list = self.obj_list.resolve(context)
- context[self.return_name] = Paginator(actual_obj_list, int(self.page_size))
- return ''
- actual_obj_list = self.obj_list.resolve(context) - вот здесь второй важный момент, actual_obj_list после вызова метода resolve(context) содержит в себе настоящий список объектов с которым мы можем творить чо хотим.
- context[self.return_name] = Paginator(actual_obj_list, int(self.page_size)) - вот тут собственно мы и творим то что хотели, т.е. создаём объект пэйджинга и записываем его в контекст шаблона