Header

Мы создаём веб сайты и веб приложения

Design is not just what it looks like and feels like

Design is how it works

Давайте сделаем что-то интересное!

вторник, 26 октября 2010 г.

Django: Как передавать переменные в шаблонный тэг.

При создании шаблонного тега часто бывает нужно что-то в него передать из контекста самого шаблона, например объект request, или какую-нибудь коллекцию с которой что-нибудь нужно сделать.

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

Комментариев нет:

Отправить комментарий