سؤال

أنا أفعل شيئًا مثل:

{% 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')}

نصائح أخرى

يبدو أن هذا تم الرد عليه من قبل ، ولكن هناك بديل. إنه شيء واحد لاستخدام معالج سياق لتتبع شيء محدد من خارج القالب ، ولكن في بعض الأحيان تريد حساب عدد المرات التي تمر بها حلقتان ، أو شيء من هذا القبيل. هناك طريقة أخرى:

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 %} علامة داخل كل كتلة أو استخدام معالج السياق لإعداد متغير "عالمي".

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top