如何在Django中创建可重用的模板?

时间:2012-02-27 20:47:23

标签: django templates django-templates jinja2

创建可重用模板的Django方法是什么?

示例:假设我的很多网页都包含“最新消息”框并遵循DRY原则,我想定义一次并在其他页面中重复使用。我如何使用Django(或Jinja2)模板?

阅读Django's Template Documentation我得到的结论是,Django模板提供了“自上而下”的继承,其中子模板本身决定了它将嵌入哪个超模板:

<!-- Super-template (not valid, for illustration): -->
<html>
  <head><title>Title</title></head>
  <body>{% block content %}{% endblock %}</body>
</html>
<!-- Sub-template: -->
{% extends "base.html" %}
{% block content %}
<div class="latest-news">News</div>
{% endblock %}

那么在几个位置重用块(子模板)的技术是什么?

8 个答案:

答案 0 :(得分:27)

重用模板片段最灵活的方法是define an inclusion_tag。您可以将参数传递给自定义标记,在Python中处理它们,然后退回到模板。 Direct inclusion仅适用于不依赖于周围环境的片段。

文档中的快速示例:

app/templatetags/poll_extras.py中注册带有装饰的标记:

from django import template
register = template.Library()

@register.inclusion_tag('results.html')
def show_results(poll):
    choices = poll.choice_set.all()
    return {'choices': choices}

app/templates/results.html

<ul>
{% for choice in choices %}
    <li> {{ choice }} </li>
{% endfor %}
</ul>

调用标签:

{% load poll_extras %}
{% show_results poll %}

答案 1 :(得分:12)

您要找的是来自Django docs{% include "template.html"%}

答案 2 :(得分:10)

如果您需要使用{% block %},则只能通过{% extend %}方法执行此操作。否则,您可以使用{% include 'some.html' %}在多个位置包含一些HTML。

答案 3 :(得分:3)

非官方Django Reusable App Conventions建议使用这些块名称:

  • {% block title %}
  • {% block extra_head %}
  • {% block body %}
  • {% block menu %}
  • {% block content %}
  • {% block content_title %}
  • {% block header %} {% block footer %}
  • {% block body_id %} {% block body_class %}
  • {% block [section]_menu %} {% block page_menu %}

如果每个人都坚持这些惯例,它应该会使这个问题更容易。点击链接查看每个区块的描述。

答案 4 :(得分:1)

如其他答案所述,最简单的方法是直接包含:

{% include 'mytemplate.html' %}

可以使用

修改渲染模板的上下文(或更简单地说,是将变量传递给模板)。
{% include 'mytemplate.html' with poll=poll %}

以传统民意调查为例,我要编写的模板为:

<div class="stylish-poll">
{% for choice in poll.choices %} <!-- poll is a template variable -->
    {% include 'choice_template.html' with choice=choice %}
{% endfor %}
</div>

要知道的另一种可能有用的事情是,only关键字可防止将模板变量poll传递到'choice_template.html'中,默认情况下该模板变量将被传递。如果您不希望选择模板有权访问{{ poll }},则include语句如下所示:

{% include 'choice_template.html' with choice=choice only %}

文档:https://docs.djangoproject.com/en/dev/ref/templates/builtins/#include

答案 5 :(得分:0)

Aïe,我的错 - 答案在Django Reference中给出(并没有在上述Django Template Documentation中讨论过)......

所以:只需使用{% include sub_template_name %}

答案 6 :(得分:0)

使用{% include %}标签的示例

  • 所有数据均来自Django后端
  • 使用card_template.html中的include标签将许多值传递给page1.html

card_template.html

<style>
    .choices_div {
        border-radius: 5rem;
    }

    .card-footer {
        background-color: transparent;
        border: transparent;
    }
</style>


<div class="col mb-5 px-4">
    <div class="card h-100 w-100 jumbotron choices_div {{ bg_color|default:'' }}">

        <div class="card-body p-0">
            <h3 class="card-title text-center">{{ card_title|capfirst }}</h3>
            <ul class="card-text mt-3">
                {% for c in card_body_list %}
                    <li>{{ c }}</li>
                {% endfor %}
            </ul>
        </div>
        <div class="card-footer text-center pt-4">
            {% if get_post_request == 1 %}
                <a class="btn btn-light" href="{{ href }}">{{ button_text }}</a>

            {% else %}
                <form method="post">
                    {% csrf_token %}
                    <button type="submit" class="btn btn-light w-75" name="category"
                            value="{{ button_value }}">{{ button_text }}</button>
                </form>
            {% endif %}
        </div>

    </div>
</div>

page1.html

{% extends 'core/core.html' %}

{% block body %}
    <div class="jumbotron bg-white">
        <div class="container">
            <div class="mb-5 text-center">
                <h1>Choose user category</h1>
                <h5>Once choosen, the user category cannot be changed</h5>
            </div>
            <div class="row row-cols-lg-2 justify-content-around">
                {% for object in object_list %}
                    {% cycle 'bg_peacock' 'bg_sunset' 'bg_skin' 'bg_brown' as bg_color silent %}
                    {% include 'core/card_template.html' with card_title=object.category card_body_list=object.description get_post_request=2 button_text='Select' bg_color=bg_color button_value=object.id %}
                {% endfor %}
            </div>
        </div>
    </div>
{% endblock %}

答案 7 :(得分:0)

尽管这个问题是多年前提出的,但无论如何我都会向您展示对我有用的方法。

base.html 在您的基本模板中,您需要定义您需要在其他模板中重用的所有块,

<html>
<head>
<meta name="description" content="{%block description%}{%endblock%}">
<meta name="keywords" content="{%block keywords%}{%endblock%}">
<title>{%block title%}{%endblock%}</title>
</head>
<body>
<!---other body stuff--->
{%block content%}
{%endblock%}
</body>
</html>

home.html

{%extends 'base.html'%}

<!--you can reuse all blocks here-->
{%block description%}Django reusable blocks, for every bage{%endblock%}
{%block keywords%}django,block, resuable,meta,title,{%endblock%}
{%block title%}django reuseable blocks for title, meta description and meta keywords{%endblock%}

{%block content%}
<div>
<h1> reuse blocks</h1>
</div>
{%endblock%}