zoukankan      html  css  js  c++  java
  • Python---Flask--02--模板

    把业务逻辑和表现逻辑混在一起会导致代码难以理解和维护。假设要为一个大型表格构建HTML 代码,表格中的数据由数据库中读取的数据以及必要的 HTML 字符串连接在一起。把表现逻辑移到模板中能够提升程序的可维护性。

    模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为渲染。为了渲染模板,Flask 使用了一个名为 Jinja2 的强大模板引擎。

    Flask 默认的模板文件存放在templates目录下面。

    创建模板

    创建teamplates/index.html模板

    <h1>Hello Flask</h1>
    

    创建teamplate/user.html模板

    <h1>{{ name }}</h1>
    

    渲染模板

    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    @app.route('/)
    def index():
        return render_template('index.html')
    
    @app.route('/user')
    def user():
        return render_template('user.html', name='Flask')
    
    
    if __name__ == '__main__':
        app.run(DEBUG=True)
    
    

    模板变量

    在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模
    板引擎这个位置的值从渲染模板时使用的数据中获取。
    Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板
    中使用变量的一些示例如下:

    <p>A value from a dictionary: {{ mydict['key'] }}.</p>
    <p>A value from a list: {{ mylist[3] }}.</p>
    <p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>
    <p>A value from an object's method: {{ myobj.somemethod() }}.</p>
    

    可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述
    模板以首字母大写形式显示变量 name 的值:

    Hello, {{ name|capitalize }}
    

    列出了 Jinja2 提供的部分常用过滤器。
    Jinja2变量过滤器

    过滤器名 说  明
    safe 渲染值时不转义
    capitalize 把值的首字母转换成大写,其他字母转换成小写
    lower 把值转换成小写形式
    upper 把值转换成大写形式
    title 把值中每个单词的首字母都转换成大写
    trim 把值的首尾空格去掉
    striptags 渲染之前把值中所有的 HTML 标签都删掉
    safe 过滤器值得特别说明一下。默认情况下,出于安全考虑,Jinja2 会转义所有变量。例
    如,如果一个变量的值为 '<h1>Hello</h1>',Jinja2 会将其渲染成 '<h1>Hello</
    h1>',浏览器能显示这个 h1 元素,但不会进行解释。很多情况下需要显示变量中存储
    的 HTML 代码,这时就可使用 safe 过滤器。

    控制结构

    Jinja2 提供了多种控制结构,可用来改变模板的渲染流程。使用简单的例子介绍其中最有用的控制结构。
    下面这个例子展示了如何在模板中使用条件控制语句:

    {% if user %}
     Hello, {{ user }}!
    {% else %}
     Hello, Stranger!
    {% endif %}
    

    另一种常见需求是在模板中渲染一组元素。下例展示了如何使用 for 循环实现这一需求:

    <ul>
     {% for comment in comments %}
     <li>{{ comment }}</li>
     {% endfor %}
    </ul>
    

    Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:

    {% macro render_comment(comment) %}
     <li>{{ comment }}</li>
    {% endmacro %}
    <ul>
     {% for comment in comments %}
     {{ render_comment(comment) }}
     {% endfor %}
    </ul>
    

    为了重复使用宏,我们可以将其保存在单独的文件中,然后在需要使用的模板中导入:

    {% import 'macros.html' as macros %}
    <ul>
     {% for comment in comments %}
     {{ macros.render_comment(comment) }}
     {% endfor %}
    </ul>
    

    需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复:

    {% include 'common.html' %}
    

    另一种重复使用代码的强大方式是模板继承,它类似于 Python 代码中的类继承。首先,创建一个名为 base.html 的基模板:

    <html>
    <head>
     {% block head %}
     <title>{% block title %}{% endblock %} - My Application</title>
     {% endblock %}
    </head>
    <body>
     {% block body %}
     {% endblock %}
    </body>
    </html>
    

    block 标签定义的元素可在衍生模板中修改。在本例中,我们定义了名为 head、title 和body 的块。注意,title 包含在 head 中。下面这个示例是基模板的衍生模板:

    {% extends "base.html" %}
    {% block title %}Index{% endblock %}
    {% block head %}
     {{ super() }}
     <style>
     </style>
    {% endblock %}
    {% block body %}
    <h1>Hello, World!</h1>
    {% endblock %}
    

    extends 指令声明这个模板衍生自 base.html。在 extends 指令之后,基模板中的 3 个块被重新定义,模板引擎会将其插入适当的位置。注意新定义的 head 块,在基模板中其内容不是空的,所以使用 super() 获取原来的内容。稍后会展示这些控制结构的具体用法,让你了解一下它们的工作原理。

    使用Flask_bootstrap 扩展

    Bootstrap(http://getbootstrap.com/)是 Twitter 开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代 Web 浏览器。
    Bootstrap 是客户端框架,因此不会直接涉及服务器。服务器需要做的只是提供引用了Bootstrap 层 叠 样 式 表(CSS) 和 JavaScript 文 件 的 HTML 响 应, 并 在 HTML、CSS 和JavaScript 代码中实例化所需组件。这些操作最理想的执行场所就是模板。
    要想在程序中集成 Bootstrap,显然要对模板做所有必要的改动。不过,更简单的方法是使用一个名为 Flask-Bootstrap 的 Flask 扩展,简化集成的过程。

    安装

    pip install flask_bootstrap

    使用

    初始化Flask_bootstrap

    from flask import Flask
    from flask_bootstrap import Bootstrap
    
    app = Flask(__name__)
    bootstarp = Bootstrap(app)
    

    templates/user.html:使用 Flask-Bootstrap 的模板

    {% extends "bootstrap/base.html" %}
    {% block title %}Flasky{% endblock %}
    {% block navbar %}
    <div class="navbar navbar-inverse" role="navigation">
     <div class="container">
     <div class="navbar-header">
     <button type="button" class="navbar-toggle"
     data-toggle="collapse" data-target=".navbar-collapse">
     <span class="sr-only">Toggle navigation</span>
     <span class="icon-bar"></span>
     <span class="icon-bar"></span>
     <span class="icon-bar"></span>
     </button>
     <a class="navbar-brand" href="/">Flasky</a>
     </div>
     <div class="navbar-collapse collapse">
     <ul class="nav navbar-nav">
     <li><a href="/">Home</a></li>
     </ul>
     </div>
     </div>
    </div>
    {% endblock %}
    {% block content %}
    <div class="container">
     <div class="page-header">
     <h1>Hello, {{ name }}!</h1>
     </div>
    </div>
    {% endblock %}
    

    Jinja2 中的 extends 指令从 Flask-Bootstrap 中导入 bootstrap/base.html,从而实现模板继承。Flask-Bootstrap 中的基模板提供了一个网页框架,引入了 Bootstrap 中的所有 CSS 和模板JavaScript 文件。
    基模板中定义了可在衍生模板中重定义的块。block 和 endblock 指令定义的块中的内容可添加到基模板中。
    上面这个 user.html 模板定义了 3 个块,分别名为 title、navbar 和 content。这些块都是基模板提供的,可在衍生模板中重新定义。title 块的作用很明显,其中的内容会出现在渲染后的 HTML 文档头部,放在 标签中。navbar 和 content 这两个块分别表示页<br> 面中的导航条和主体内容。<br> 在这个模板中,navbar 块使用 Bootstrap 组件定义了一个简单的导航条。content 块中有个<div> 容器,其中包含一个页面头部。之前版本的模板中的欢迎信息,现在就放在这个页面头部。</p> <p>Flask-Bootstrap 的 base.html 模板还定义了很多其他块,都可在衍生模板中使用。表 3-2 列<br> 出了所有可用的快。<br> Flask-Bootstrap基模板中定义的块</p> <table> <thead> <tr> <th>块  名</th> <th>说  明</th> </tr> </thead> <tbody> <tr> <td>doc</td> <td>整个 HTML 文档</td> </tr> <tr> <td>html_attribs</td> <td><html> 标签的属性</td> </tr> <tr> <td>html</td> <td><html> 标签中的内容</td> </tr> <tr> <td>head</td> <td><head> 标签中的内容</td> </tr> <tr> <td>title</td> <td><title> 标签中的内容</td> </tr> <tr> <td>metas</td> <td>一组 <meta> 标签</td> </tr> <tr> <td>styles</td> <td>层叠样式表定义</td> </tr> <tr> <td>body_attribs</td> <td><body> 标签的属性</td> </tr> <tr> <td>body</td> <td><body> 标签中的内容</td> </tr> <tr> <td>navbar</td> <td>用户定义的导航条</td> </tr> <tr> <td>content</td> <td>用户定义的页面内容</td> </tr> <tr> <td>scripts</td> <td>文档底部的 JavaScript 声明</td> </tr> <tr> <td>表 中的很多块都是 Flask-Bootstrap 自用的,如果直接重定义可能会导致一些问题。例如,Bootstrap 所需的文件在 styles 和 scripts 块中声明。如果程序需要向已经有内容的块中添加新内容,必须使用 Jinja2 提供的 super() 函数。例如,如果要在衍生模板中添加新的 JavaScript 文件,需要这么定义 scripts 块:</td> <td></td> </tr> </tbody> </table> <pre><code>{% block scripts %} {{ super() }} <script type="text/javascript" src="my-script.js"></script> </code></pre> <h3 id="模板中的链接">模板中的链接</h3> <p>任何具有多个路由的程序都需要可以连接不同页面的链接,例如导航条。</p> <p>在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的依赖关系。如果重新定义路由,模板中的链接可能会失效。<br> 为了避免这些问题,Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存的信息生成 URL。</p> <p>url_for() 函数最简单的用法是以视图函数名(或者 app.add_url_route() 定义路由时使用的端点名)作为参数,返回对应的 URL。例如,在当前版本的 hello.py 程序中调用 url_for('index') 得到的结果是 /。调用 url_for('index', _external=True) 返回的则是绝对地<br> 址,在这个示例中是 <a href="http://localhost:5000/%E3%80%82%E7%94%9F%E6%88%90%E8%BF%9E%E6%8E%A5%E7%A8%8B%E5%BA%8F%E5%86%85%E4%B8%8D%E5%90%8C%E8%B7%AF%E7%94%B1%E7%9A%84%E9%93%BE%E6%8E%A5%E6%97%B6%EF%BC%8C%E4%BD%BF%E7%94%A8%E7%9B%B8%E5%AF%B9%E5%9C%B0%E5%9D%80%E5%B0%B1%E8%B6%B3%E5%A4%9F%E4%BA%86%E3%80%82%E5%A6%82%E6%9E%9C%E8%A6%81%E7%94%9F%E6%88%90%E5%9C%A8%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B9%8B%E5%A4%96%E4%BD%BF%E7%94%A8%E7%9A%84%E9%93%BE%E6%8E%A5%EF%BC%8C%E5%88%99%E5%BF%85%E9%A1%BB%E4%BD%BF%E7%94%A8%E7%BB%9D%E5%AF%B9%E5%9C%B0%E5%9D%80%EF%BC%8C%E4%BE%8B%E5%A6%82%E5%9C%A8%E7%94%B5%E5%AD%90%E9%82%AE%E4%BB%B6%E4%B8%AD%E5%8F%91%E9%80%81%E7%9A%84%E9%93%BE%E6%8E%A5%E3%80%82" target="_blank">http://localhost:5000/。生成连接程序内不同路由的链接时,使用相对地址就足够了。如果要生成在浏览器之外使用的链接,则必须使用绝对地址,例如在电子邮件中发送的链接。</a></p> <p>使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如,url_for('user', name='john', _external=True) 的返回结果是 <a href="http://localhost:5000/user/john%E3%80%82" target="_blank">http://localhost:5000/user/john。</a></p> <p>传入 url_for() 的关键字参数不仅限于动态路由中的参数。函数能将任何额外参数添加到查询字符串中。例如,url_for('index', page=2) 的返回结果是 /?page=2。</p> <h3 id="静态文件">静态文件</h3> <p>Web 程序不是仅由 Python 代码和模板组成。大多数程序还会使用静态文件,例如 HTML代码中引用的图片、JavaScript 源码文件和 CSS。</p> <p>这是因为对静态文件的引用被当成一个特殊的路由,即 /static/<filename>。例如,调用url_for('static', filename='css/styles.css', _external=True) 得 到 的 结 果 是 <a href="http://localhost:5000/static/css/styles.css%E3%80%82" target="_blank">http://localhost:5000/static/css/styles.css。</a></p> <p>默认设置下,Flask 在程序根目录中名为 static 的子目录中寻找静态文件。如果需要,可在static 文件夹中使用子文件夹存放文件。服务器收到前面那个 URL 后,会生成一个响应,包含文件系统中 static/css/styles.css 文件的内容。</p> <p>如何在程序的基模板中放置 favicon.ico 图标。这个图标会显示在浏览器的<br> 地址栏中。<br> templates/base.html:定义收藏夹图标</p> <pre><code>{% block head %} {{ super() }} <link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon"> <link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}" type="image/x-icon"> {% endblock %} </code></pre> <p>图标的声明会插入 head 块的末尾。注意如何使用 super() 保留基模板中定义的块的原始内容。</p>

    僵尸将臣
  • 相关阅读:
    7月的尾巴,你是XXX
    戏说Android view 工作流程《下》
    “燕子”
    Android开机动画bootanimation.zip
    戏说Android view 工作流程《上》
    ViewController里已连接的IBOutlet为什么会是nil
    My first App "Encrypt Wheel" is Ready to Download!
    iOS开发中角色Role所产生的悲剧(未完)
    UIScrollView实现不全屏分页的小技巧
    Apple misunderstood my app,now my app status changed to “In Review”
  • 原文地址:https://www.cnblogs.com/sunshenggang/p/11063384.html
Copyright © 2011-2022 走看看