zoukankan      html  css  js  c++  java
  • flask模板结构组织(局部模板、宏、模板继承)--

    模板结构组织

    除了使用函数、过滤器等工具控制模板的输出外,jinja2还提供了一些工具来在宏观上组织模板内容。

    局部模板

    在Web程序中,我们通常会为每一类页面编写一个独立的模板。比如主页模板、用户资料也模板、设置页模板等。这些模板可以直接在视图函数中渲染并作为HTML响应主题。除了这类模板,我们还会用到另一类非独立模板,这类模板通常被称为局部模板或此模板,因为它们仅包含部分代码,所以我们不会在视图函数中直接渲染它,而是插入到其他独立模板中。

    当某个视图用来处理ajax请求时,返回的数据不需要包含完整的HTML结构,这时就可以返回渲染后的局部模板。

    当多个独立的模板中都会使用同一块HTML代码时,我们可以把这部分代码抽离出来,存储到局部模板中。这样一方面可以避免重复,另一方面也可以方便统一管理。比如,多个页面中都要在页面顶部显示一个提示条,这个横幅可以定义在局部模板_banner.html中。

    我们使用include标签来插入一个局部模板,这会把局部模板的全部内容插在使用include标签的位置。

    比如在其他模板中,我们可以在任意位置使用下面的代码插入_banner.html的内容:

    {% include ‘_banner.html’ %}

    为了和普通模板区分开,局部模板的命名通常以一个下划线开始。

    宏(macro)是jinja2提供的一个非常有用的特性,它类似python中的函数。使用宏可以把一部分模板代码封装到宏里,使用传递的参数来构建内容,最后返回构建后的内容。在功能上,它和局部模板类似,都是为了方便代码块的重用。

    为了便于管理,可以把宏存储在单独的文件中,这个文件通常命名为macros.html或_macros.html。在创建宏时,使用macro和endmacro标签声明宏的开始和结束。在开始标签中定义宏的名称和接收的参数

    例子:

    {% macro qux(amount=1) %}
        {% if amount == 1 %}
            I am qux.
        {% elif amount > 1 %}
            We are quxs.
    {% endmacro %}

    使用时,需要向从python模块中导入函数一样使用import语句导入它,然后作为函数调用,传入必要的参数,例如:

    {% from 'macros.html' import qux %}
    ...
    {{ qux(amount=5) }}

    另外,在使用宏时我们需要注意上下文问题,在jinja2中,出于性能的考虑,并且为了让一切保持显示,默认情况下包含(include)一个局部模板会传递当前上下文到局部模板中,但导入(import)不会。具体来说,当我们使用render_template()函数渲染一个foo.html模板时,这个foo.html的模板上下文中包含下列对象:

    1 flask使用内置的模板上下文处理函数提供的g、session、config、request。

    2 扩展使用内置的模板上下文处理函数提供的变量。

    3 自定义模板上下文处理传入的变量

    4 使用render_template()函数传入的变量

    5 jinja2和flask内置及自定义全局对象。

    6 jinja2内置及自定义过滤器

    7 jinja2内置及自定义测试器

    使用include标签插入的局部模板(比如_banner.html)同样可以使用上述上下文中的变量和函数。而导入另一个并非直接渲染的模板(比如macro.html)时,这个模板进包含下列这些对象:

    1 jinja2和flask内置的全局函数和自定义全局函数

    2 jinja2内置及自定义过滤器

    3 jinja2内置及自定义测试器

    因此,如果我们想在导入的宏中使用第一个列表中的2、3、4项,就需要在导入时显示地使用with context声明传入当前模板的上下文:

    {% from “macros.html” import foo with context %}

    虽然flask使用内置的模板上下文处理函数传入session、g、request和config,但它同时也使用app.jinja_env.globals字典将这几个变量设置为全局变量,所以我们仍然可以在不显示声明传入上下文的情况下,直接在导入的宏中使用它们。

    模板继承

    jinja2的模板继承允许你定义一个基模板,把网页上的导航栏、页脚等通用内容放在基模板中,而每一个继承基模板的子模板在被渲染时都会自动包含这些部分。使用这种方式可以避免在多个模板中编写重复的代码。

    编写基模板

    基模板存储了程序页面的固定部分,通常被命名为base.html或layout.html。实例程序中的基模板base.html中包含了一个基本的HTML结构,我们还添加了一个简单的导航条和页脚

    <!DOCTYPE html>
    <html lang="en">
    <head>
        {% block head %}
            <meta charset="utf-8">
            <title>{% block title %}Template - HelloFlask{% endblock %}</title>
            {% block styles %}{% endblock %}
        {% endblock %}
    </head>
    <body>
    <nav>
        <ul><li><a href="{{ url_for('index') }}">Home</a></li></ul>
    </nav>
    <main>
        {% block content %}{% endblock %}
    </main>
    <footer>
        {% block footer %}
            ...
        {% endblock %}
    </footer>
    {% block sripts %}{% endblock %}
    </body>
    </html>

    当子模板继承基模板后,子模板会自动包含基模板的内容和结构。为了能够让子模板方便地覆盖或插入内容到基模板中,我们需要在基模板中定义块(block),在子模板中可以通过定义同名的块来执行继承操作。

    块的开始和结束分别使用block和endblock标签声明,而且快之间可以嵌套。在这个基模板中,我们创建了6个块:head、title、styles、content、footer和scripts,分别用来划分不同的代码。其中,head块表示<head>标签的内容,title表示<title>标签的内容,content块表示页面主题内容,footer表示页脚部分,styles块和scripts块分别用来包含CSS文件和javaScript文件引用链接或页内的CSS和javaScript代码。

    这里的块名称可以随意指定,而且并不是必须的。你可以按照需要设置块,如果只需要让字模板添加主体内容,那么仅定义一个content块就足够了。

    以content块为例,模板继承示意图如下:

    为了避免块的混乱,块的结束标签可以指明块名,同时要确保前后名称一致。

    如:

    {% block body %}

    {% endblock body %}

    编写子模板

    因为基模板中定义了HTML的基本结构,而且包含了页脚等固定信息,在子模板中我们不再需要定义这些内容,只需要对特定的块进行修改。这时我们可以修改前面创建的电影清单模板watchlist.html和主页模板index.html,将这些子模板的通用部分合并到基模板中,并在子模板中定义块来组织内容,以便在渲染时将块中的内容插入到基模板的对应位置。

    以index.html为例,修改后的index.html子模板如下:

    {% extends 'base.html' %}
    {% from 'macros.html' import qux %}

    {% block content %}
    {% set name='baz' %}
    <h1>Template</h1>
    <ul>
        <li><a href="{{ url_for('watchlist') }}">Watchlist</a></li>
        <li>Filter:{{ foo|musical }}</li>
        <li>Global:{{ bar() }}</li>
        <li>Test:{% if name is baz %}I am baz.{% endif %}</li>
        <li>Macro: {{ qux(amount=5) }}</li>
    </ul>
    {% endblock %}

    我们使用extends标签声明扩展基模板,它告诉模板引擎当前模板继承base.html

    extends必须是字模板的第一个标签。

    我们在基模板中定义了四个块,在子模板中,我们可以对父模板中的块进行两种操作:

    1 覆盖内容

    当在字模板里创建同名的块时,会使用子块的内容覆盖父块的内容。比如在字模板index.html中定义了title块,内容为Home,这会把块中的内容填充到基模板里的title块的位置,最终渲染为<title>Home</title>,content块的效果同理。

    2 追加内容

    如果要向基模板中的块追加内容,需要使用jinja2提供的super()函数进行声明,这会向父块添加内容。比如,下面例子中向基模板中的styles块追加了一行<style>样式定义:

    {% block styles %}
    {{ super() }}
    <style>
        .foo{
            color:red;
        }
    </style>
    {% endblock %}

    当字模板被渲染时,它会继承基模板的所有内容,然后根据我们定义的块进行覆盖或追加操作,渲染子模板index.html的结果:

    相当于把base.html的内容先拷贝过来,然后根据子模板中的内容进行定型,比如覆盖了什么块

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
            <title>Template - HelloFlask}</title>
    </head>
    <body>
    <nav>
        <ul><li><a href="/">Home</a></li></ul>
    </nav>
    <main>
        <h1>Template</h1>
        <ul>
            <li><a href="/watchlist">Watchlist</a></li>
            <li>Filter:I am foo.&#9835;</li>
            <li>Global:I am bar.</li>
            <li>Test:I am baz.</li>
            <li>Macro: We are quxs.</li>
        </ul>
    </main>
    <footer>
        ...
    </footer>
    </body>
    </html>
  • 相关阅读:
    CSS
    javaScript的DOM操作
    模板Template
    Django的View(视图)
    路由系统(urls.py)
    MTV和MVC模型和创建Django项目
    rest-framework认证组件
    property classmethod staticmethod和反射
    ModelSerializer和视图
    rest-framework序列化
  • 原文地址:https://www.cnblogs.com/xiaxiaoxu/p/10434386.html
Copyright © 2011-2022 走看看