質問

次のようなことをしています:

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

Djangoのドキュメントには、url templatetagがコンテキストで変数を定義できると書かれていますが、次のブロックで object_url の値を取得できません。

URLテンプレートタグを各ブロックの先頭に配置すると機能しますが、「自分自身を繰り返し」はしたくありません。

誰もがより良い解決策を知っていますか?

役に立ちましたか?

解決

URLがビュー固有の場合、ビューからURLを渡すことができます。 URLをテンプレートで真にグローバルにする必要がある場合は、コンテキストプロセッサ:

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

他のヒント

これは以前に回答されたように見えますが、別の方法があります。コンテキストプロセッサを使用して、テンプレートの外部から定義された何かを追跡することは1つのことですが、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

カスタムテンプレートタグを作成できます:

@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 ''

まあ、これは一種のテンプレート継承を乱用していますが、 {{block.super}} を使用して、object_urlをブロックに挿入します。

つまり、中間レベルのテンプレートで次のことを行います。

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

そして、ブロックテンプレートで次を使用します。

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

これは、 {{object_url}} 以外のものをブロックに入れないようにするため、素晴らしいアイデアではありませんが、機能します。あなたが私からそれを得たと誰にも言わないでください!

継承されたすべてのテンプレートで、ブロックの再定義以外のコードは実行されません。したがって、この例では、各ブロック内で {%url%} タグを呼び出すか、コンテキストプロセッサを使用して" global"を設定する必要があります。変数。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top