2009-06-23 4 views
5

Я делаю что-то вроде:Определение «глобальной переменной» в Django шаблоны

{% extends 'base.html' %} 
{% url myapp.views.dashboard object as object_url %} 
{% block sidebar %} 
... {{ object_url }} ... 
{% endblock %} 
{% block content %} 
... {{ object_url }} ... 
{% endblock %} 

Джанго документация говорит URL templatetag может определить переменную в контексте, но я не получаю никакого значения для object_url в следующем блоки.

Если я поместил шаблон templatetag в начале каждого блока, он работает, но я не хочу «повторять себя».

Кто-нибудь знает лучшее решение?

ответ

7

Если URL-адрес определен, вы можете передать URL-адрес из своего представления. Если URL должен быть по-настоящему глобальный шаблонах, вы можете поместить его в a context processor:

def object_url(request): 
    return {'object_url': reverse('myapp.views.dashboard')} 
+0

+1, вы» быстрее меня. – SingleNegationElimination

+0

Ум, многие виды используют эту переменную, но не все. Кроме того, я использую тот же шаблон для других типов переменных, определенных моими пользовательскими templatetags. Вышеприведенное выше дело просто упрощено, поэтому я считаю, что нецелесообразно принимать решение так, как оно есть. – Achimnol

+3

Даже если он не используется в каждом шаблоне, это не повредит чем-либо, чтобы помещать его в контекстный процессор ... если он не выполняет поиск базы данных, конечно, и в этом случае это может повлиять на производительность сайта. –

0

Ну, это своего рода оскорбительных наследования шаблонов, но вы можете использовать {{block.super}} поставить object_url в свои блоки.

Другими словами, в шаблоне среднего уровня сделать:

{% block sidebar %}{{ object_url }}{% endblock %} 
{% block content %}{{ object_url }}{% endblock %} 

И тогда в вашем блоке шаблонов используйте:

{% block sidebar %} 
... {{ block.super }}... 
{% endblock %} 

Это не хорошая идея, потому что это мешает вам положить что-нибудь кроме {{ object_url }} в ваш блок ... но он работает. Просто не говорите никому, у кого это есть у меня!

+0

Я должен добавить, что лично я предпочитаю быть явным и делать нагрузку в каждом шаблоне. Мне становится легче видеть, откуда мои данные. –

0

В каждом унаследованном шаблоне не выполняется какой-либо код за пределами переопределений блоков. Поэтому в вашем примере вам нужно вызвать тег {% url %} внутри каждого блока или использовать контекстный процессор для установки «глобальной» переменной.

2

Похоже, ранее был дан ответ, но есть альтернатива. Одно дело использовать процессор контекста, чтобы отслеживать что-то определенное из-за пределов шаблона, но иногда вы хотите посчитать количество раз, когда проходят две петли, или что-то в этом роде. Существует еще один способ:

class GlobalVariable(object): 
    def __init__(self, varname, varval): 
    self.varname = varname 
    self.varval = varval 
    def name(self): 
    return self.varname 
    def value(self): 
    return self.varval 
    def set(self, newval): 
    self.varval = newval 

class GlobalVariableSetNode(template.Node): 
    def __init__(self, varname, varval): 
    self.varname = varname 
    self.varval = varval 
    def render(self, context): 
    gv = context.get(self.varname, None) 
    if gv: 
     gv.set(self.varval) 
    else: 
     gv = context[self.varname] = GlobalVariable(self.varname, self.varval) 
    return '' 
def setglobal(parser, token): 
    try: 
    tag_name, varname, varval = token.contents.split(None, 2) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires 2 arguments" % token.contents.split()[0]) 
    return GlobalVariableSetNode(varname, varval) 
register.tag('setglobal', setglobal) 

class GlobalVariableGetNode(template.Node): 
    def __init__(self, varname): 
    self.varname = varname 
    def render(self, context): 
    try: 
     return context[self.varname].value() 
    except AttributeError: 
     return '' 
def getglobal(parser, token): 
    try: 
    tag_name, varname = token.contents.split(None, 1) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0]) 
    return GlobalVariableGetNode(varname) 
register.tag('getglobal', getglobal) 

class GlobalVariableIncrementNode(template.Node): 
    def __init__(self, varname): 
    self.varname = varname 
    def render(self, context): 
    gv = context.get(self.varname, None) 
    if gv is None: 
     return '' 
    gv.set(int(gv.value()) + 1) 
    return '' 
def incrementglobal(parser, token): 
    try: 
    tag_name, varname = token.contents.split(None, 1) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0]) 
    return GlobalVariableIncrementNode(varname) 
register.tag('incrementglobal', incrementglobal) 

Это позволяет использовать его в шаблоне, например так:

{% setglobal ii 0 %} 
... 
{% for ... %} 
    {% incrementglobal ii %} 
    current={% getglobal ii %} 
{% endfor %} 
... 
{% for ... %} 
    {% incrementglobal ii %} 
    current={% getglobal ii %} 
{% endfor %} 
... 
total of 2 loops={% getglobal ii %} 
... 
{% setglobal ii 0 %} 
... 
do something else now that {% getglobal ii %} is back to 0 
1

Вы можете написать пользовательский тег шаблона:

@register.simple_tag(takes_context=True) 
def set_global_context(context, key, value): 
    """ 
    Sets a value to the global template context, so it can 
    be accessible across blocks. 

    Note that the block where the global context variable is set must appear 
    before the other blocks using the variable IN THE BASE TEMPLATE. The order 
    of the blocks in the extending template is not important. 

    Usage:: 
     {% extends 'base.html' %} 

     {% block first %} 
      {% set_global_context 'foo' 'bar' %} 
     {% endblock %} 

     {% block second %} 
      {{ foo }} 
     {% endblock %} 
    """ 
    context.dicts[0][key] = value 
    return '' 
+0

Я сам использовал этот подход, и он отлично работает для кода и удобочитаемости. Глобальную переменную, измененную случайным образом по всем шаблонам, очень сложно отлаживать. Создание конечного автомата с использованием шаблона сохраняет логику в одном месте, это имеет много преимуществ. –

Смежные вопросы