【问题标题】:Django template conditional variable assignmentDjango 模板条件变量赋值
【发布时间】:2023-04-03 06:08:01
【问题描述】:

我想根据变量是否存在为变量分配不同的值,这可能吗?我的非工作示例可能会更清楚:

{% if username %}
    {% with menu_user=username %}
{% elif recent_users %}
    {% with sorted_users=recent_users|dictsortreversed:"timestamp" %}
    {% with menu_user=sorted_users.0.username %}
{% endif %}
{% if menu_user %}
    <div id="menu">
        <ul>
            <li><a href="/user/{{ menu_user|urlencode }}">Profile</a></li>
            <li><a href="/user/{{ menu_user|urlencode }}/products/">Products</a></li>
        </ul>
    </div>
{% endif %}
{% if recent_users %}
    {% endwith %}
{% endif %}
    {% endwith %}

我尝试做的伪代码:

if username:
    menu_user = username
elif recent_users:
    menu_user = sorted(recent_users)[0]['username']

if menu_user:
    <div id="menu">
        <ul>
            <li><a href="/user/{{ menu_user|urlencode }}">Profile</a></li>
            <li><a href="/user/{{ menu_user|urlencode }}/products/">Products</a></li>
        </ul>
    </div>

【问题讨论】:

  • 你应该把这种逻辑放在 view 层。尽量保持模板尽可能简单。
  • @seler 问题是每个页面都应该呈现这个并且会有很多样板代码,这就是为什么我只希望它在基本模板中的一个位置。

标签: django django-templates django-1.4


【解决方案1】:

模板标签:

@register.assignment_tag
def alias(obj):
    """
    Alias Tag
    """
    return obj

模板:

{% alias sorted_users.0.username as menu_user %}

【讨论】:

  • with标签有什么区别?
  • 我可能错了,这是很久以前的事了,但我认为with 标签包含了代码,而这可以用于任何类似于在常规python代码中声明变量的地方。您可以将其声明为空,然后在if 中重新分配它:它的值将保留在if 之外。这不是一个好的做法,但在某些时候可能会有用。
  • 注意,as of Django 1.9,我们需要使用simple_tag而不是assignment_tag
【解决方案2】:

更新 然后最好自定义一个模板标签,如

@register.inclusion_tag('menu_snippet.html')  # or you could use takes_context=True and fetch values from the context
def render_menu(username, recent_users):
    if username:
        menu_user = username
    elif recent_users:
        # sorted here could be replaced by min or QuerySet method, it depends
        # for example: 
        # menu_user = min(recent_users, key=lambda u:u.timestamp).username
        menu_user = sorted(recent_users)[0]['username']
    return {'menu_user':menu_user}

# in template, it looks like
{% render_menu username recent_users %}

将代码放在视图中会好很多。就像你的伪代码一样,干净易读。

如果你还想写模板,我更喜欢类似的东西

{% if username %}
    <div id="menu">
        <ul>
            <li><a href="/user/{{ username|urlencode }}">Profile</a></li>
            <li><a href="/user/{{ username|urlencode }}/products/">Products</a></li>
        </ul>
    </div>
{% else %}
    {% if recent_users %}
    {% with sorted_users=recent_users|dictsortreversed:"timestamp" %}
    {% with menu_user=sorted_users.0.username %}
    <div id="menu">
        <ul>
            <li><a href="/user/{{ menu_user|urlencode }}">Profile</a></li>
            <li><a href="/user/{{ menu_user|urlencode }}/products/">Products</a></li>
        </ul>
    </div>
    {% endwith %}{% endwith %}
    {% endif %}
{% endif %}

根据您的实际使用情况,自定义模板标签或包含标签也可能有用。

【讨论】:

  • 这就是我现在拥有的方式,但菜单非常大,我不想多次使用它。此页面是基本模板,因此它会显示在每个页面上,这就是我不想在视图中执行此操作的原因,因为有太多视图应该显示此(全部)。
  • @olofom 更新了答案,然后你可以使用一些自定义标签。
  • 听起来更好,我稍后再看看。不知道如何在模板中调用它,我只使用过滤器和|。
  • @olofom 只需致电{% render_menu username recent_users %},查看the doc
  • 小优化,可以在同一个“with”标签内同时分配sorted_user和menu_user
【解决方案3】:

创建一个模板标签,将 username 和 recent_users 作为参数,然后输出菜单。这样一来,您的模板就不会受到这种逻辑的影响。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 2020-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-25
    • 2019-10-08
    相关资源
    最近更新 更多