5 марта 2014 г.

django: самодельный if-else тег

Здесь пример самодельного тега шаблонизатора django, выполняющего роль if-else-endif. Мой код подразумевает переменную 'current_statuskey' в контексте (кладётся напрямую или с помощью middleware). Писал для очень сложной страницы с кучей частей, имеющих разный вид в зависимости от статуса. Вообще там ещё у меня дополнительная логика, но это минимальный пример здесь. Использование в шаблоне:
{% ifstatus one,five,blabla %}
...
{% else %}
...
{% endifstatus %}
Можно было описать в десяток строк, но здесь больше и код очень сильно похож на стандартные теги ifequals и сопутствующие, откуда я его и адаптировал, чтобы получить более правильную и канонiчную реализацию.
from django.template.base import Node, NodeList, TemplateSyntaxError, Library

 register = Library()


class IfStatusNode(Node):
    child_nodelists = ('nodelist_true', 'nodelist_false')

     def __init__(self, varlist, nodelist_true, nodelist_false, negate):
        self.varlist = varlist
        self.nodelist_true, self.nodelist_false = nodelist_true, nodelist_false
        self.negate = negate

     def __repr__(self):
        return ""

     def render(self, context):
        current_statuskey = context.get('current_statuskey', None)
        if (self.negate and current_statuskey not in self.varlist) or (not self.negate and current_statuskey in self.varlist):
            return self.nodelist_true.render(context)
        return self.nodelist_false.render(context)


def do_ifequal(parser, token, negate):
    bits = list(token.split_contents())
    if len(bits) != 2:
        raise TemplateSyntaxError("%r takes one arguments" % bits[0])
    end_tag = 'end' + bits[0]
    nodelist_true = parser.parse(('else', end_tag))
    token = parser.next_token()
    if token.contents == 'else':
        nodelist_false = parser.parse((end_tag,))
        parser.delete_first_token()
    else:
        nodelist_false = NodeList()
    #status1,status2
    #"status1,status2, status3"
    stats = bits[1]
    if stats.startswith('"') and stats.endswith('"'):
        stats = stats[1:-1]
    varlist = [x.strip() for x in stats.split(',')]
    return IfStatusNode(varlist, nodelist_true, nodelist_false, negate)


@register.tag
def ifstatus(parser, token):
    """
    current_statuskey must be in request.
    check that the status is one of the values separated by commas.
    """
    return do_ifequal(parser, token, False)


@register.tag
def ifnotstatus(parser, token):

    return do_ifequal(parser, token, True)

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

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