资讯专栏INFORMATION COLUMN

Flask Web Development —— 模板(上)

fizz / 3206人阅读

摘要:用真实的值替换变量并返回最终响应字符串,这个过程称为渲染。示例展示模板实现该响应。控制结构提供一些控制结构用于改变模板流。这个示例展示如何使用循环做到这些同样支持宏,这和代码中的函数很像。

写代码最关键的是要易于维护且结构清晰整洁。目前为止,你看到的例子都过于简单从而没有做这方面的要求。Flask视图函数希望将两个应该完全独立的任务一并处理,两个任务有两种代码,一并处理势必会引发问题。

明摆着的任务就是生成响应,就像你在第二章看到的示例那样。对于最简单的请求确实已经足够,但是一般而言一个请求会触发应用程序的状态发生改变,而视图函数就是产生这个改变的地方。

例如,用户在网站上注册一个新的账户。用户输入邮箱地址和密码到表单并点击提交按钮。一个包含数据的请求从用户到服务器,Flask将其派发给视图函数去处理这个注册请求。这个视图函数需要告诉数据库添加新的用户并生成一个响应发回给浏览器。这两类任务通常被称作业务逻辑显示逻辑

混合业务逻辑和显示逻辑会导致代码非常的难以理解和维护。想象一下,将从数据库获取的数据和必要的HTML字符串文字进行连接,生成一堆的HTML代码是多么蛋疼的一件事情。而如果将显示逻辑移到模板中去,则势必极大提高应用程序的可维护性。

模板就是包含响应文本的文件,带有占位符变量的动态部分只在请求上下文中被知道。用真实的值替换变量并返回最终响应字符串,这个过程称为渲染。对于渲染模板任务,Flask使用强大的模板引擎Jinja2

1、Jinja2模板引擎

Jinja2模板最简单的形式就是一个包含响应文本的文件。示例3-1展示了Jinja2模板匹配示例2-1中index()视图函数响应。

示例3-1. templates/index.html:Jinja2模板

html

Hello World!

示例2-2中视图函数user()返回的响应有一个动态部分,该部分由一个变量代表。示例3-2展示模板实现该响应。

示例3-2. templates/user.html:Jinja2模板

html

Hello, {{ name }}!

1.1、渲染模板

Flask默认会在应用程序的templates子目录中寻找模板。下个版本的hello.py,你需要将之前定义的index.htmluser.html模板存放到新的templates文件夹下。

应用程序中的视图函数需要修改来渲染这些模板。示例3-3中会展示这些变化。

示例3-3. hello.py:渲染模板

pythonfrom flask import Flask, render_template

# ...

@app.route("/index")
def index():
    return render_template("index.html")

@app.route("/user/")
def user(name):
    return render_template("user.html", name=name)

render_template函数由集成Jinja2模板引擎的Flask提供。这个函数将模板的文件名作为它的第一个参数。任何附加的参数都是一个键/值对,分别对应被模板引用的变量和真实值。在这个示例中,第二个模板收到name变量。

类似于name=name的关键字参数在前面的示例中是非常常见的,但如果你不使用就很容易混淆且非常难理解。左边的“name”代表参数名称,一般在模板中用于占位符。右边的“name”在当前范围内是一个变量,为同名的参数提供真实的值。

  

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 3a来切换到这个版本的应用程序。

1.2、变量

示例3-2的模板中的{{ name }}结构引用一个变量,特殊的占位符告诉模板引擎,那个地方的值应该从模板被渲染时提供的数据中获取。

Jinja2识别任何类型的变量,包括复杂的列表、字典和对象。下面是一些模板中使用变量的示例:

html

A value from a dictionary: {{ mydict["key"] }}.

A value from a list: {{ mylist[3] }}.

A value from a list, with a variable index: {{ mylist[myintvar] }}.

A value from an object"s method: {{ myobj.somemethod() }}.

变量可以通过filters来修改,以|为分隔符添加在变量名后。例如,下面的模板展示变量大写:

htmlHello, {{ name|capitalize }}

表格3-1列出一些常用的Jinja2过滤器。

表格3-1. Jinja2变量过滤器

safe是比较有趣的一个过滤器。出于安全考虑,默认情况下,Jinja2会转义所有变量。例如,如果设置变量的值为"

Hello

",Jinja2将渲染字符串为"

Hello

"
,这将使得h1元素显示出来且不能被浏览器解释。很多时候有必要显示存储在变量中的HTML代码,对于这些情况就可以使用safe过滤器。

  

警告:永远不要在不信任的值中使用safe过滤器,例如用户在web表单中输入的文本。

完整的过滤器列表可以从Jinja2官方文档中获取。

1.3、控制结构

Jinja2提供一些控制结构用于改变模板流。这一节用简单例子来介绍一些最有用的。

下面的示例展示条件语句是怎样在模板中使用的:

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

渲染一列元素在模板中是经常用到的。这个示例展示如何使用for循环做到这些:

html
    {% for comment in comments %}
  • {{ comment }}
  • {% endfor %}

Jinja2同样支持,这和Python代码中的函数很像。例如:

html{% macro render_comment(comment) %} 
  
  • {{ comment }}
  • {% endmacro %}
      {% for comment in comments %} {{ render_comment(comment) }} {% endfor %}

    为了提高宏的复用性,可以将它们保存为多带带的文件,然后在所有需要的地方import即可:

    html{% import "macros.html" as macros %}
    
    
    
    
      {% for comment in comments %} {{ macros.render_comment(comment) }} {% endfor %}

    需要在一些地方重复使用的模板代码可以保存为一个多带带的文件,所有模板都可以include它来避免重复:

    {% include "common.html" %}
    

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

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

    这里block标签定义的派生模板是可变的。在这个示例中,有headtitlebody块;注意title包含在head中。下面的示例是一个基础模块的派生模块:

    html{% extends "base.html" %}
    {% block title %}Index{% endblock %}
    {% block head %}
        {{ super() }}
        
    {% endblock %}
    {% block body %} 
    

    Hello, World!

    {% endblock %}

    extends指令定义这个模板由base.html派生。紧随这个指令之后的是三个在基础模板中定义的块,它们将在合适的位置插入。注意在基础模板中新定义的head块是不为空的,所以使用super() 保留原来的内容。

    本节呈现的所有控制结构的实际运用将在后面展示,你会有机会看到它们是怎样工作的。

    文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

    转载请注明本文地址:https://www.ucloud.cn/yun/37435.html

    相关文章

    • Flask Web Development —— Web表单(

      摘要:每个表单域都可以连接到一个或多个是一个用于检查用户提交的输入是否合法的函数。表单域构造函数的第一个参数是一个,在渲染表单到时会使用。验证确保提交的表单域不为空。表单域验证都是直接从包中导入。表格展示了一组支持的标准表单域。 第二章中介绍的request对象公开了所有客户端发送的请求信息。特别是request.form可以访问POST请求提交的表单数据。 尽管Flask的request...

      CODING 评论0 收藏0
    • Flask Web Development —— 模板(中)

      摘要:示例使用的模板的指令通过从引用来实现模板的继承。上面的模板定义了三个,分别命名为和。同时返回相应错误的数字状态码。示例带有导航栏的基础应用程序模板这个模板中的块中只是一个名为的元素,它包含了在派生模板中定义的名为的空。 2、集成Twitter Bootstrap的Flask-Bootstrap Bootstrap是Twitter的一个开源框架,提供用户交互组件来创建一个清新且有吸引力...

      eternalshallow 评论0 收藏0
    • Flask Web Development —— 模板(下)

      摘要:如果路由重组,模板中的链接将被打断而变得无法访问。静态文件应用程序不仅仅是由代码和模板组成。当服务器收到来自之前示例的,它会产生一个响应包含的文件内容。一个优雅的解决方案是允许服务器只发送时间给浏览器,由浏览器转为当地时间并渲染。 4、链接 任何应用程序都有多个路由,必然需要包含链接来连接不同的页面,例如导航栏。 在模板中,对于简单的路由直接写URLs做链接是非常琐碎麻烦的,而给带...

      raoyi 评论0 收藏0
    • Flask Web Development —— Email

      摘要:函数携带目的地址主题邮件体模板和一组关键字参数。许多扩展操作是在假设有活动的应用程序和请求上下文的情况下进行的。但是当函数在一个不同的线程上执行,应用程序上下文需要人为地创建使用。例如,执行函数可以将邮件发送到的任务队列中。 许多类型的应用程序都会在某些事件发生的时候通知用户,常用的沟通方法就是电子邮件。尽管在Flask应用程序中,可以使用Python标准库中的smtplib包来发送电...

      SKYZACK 评论0 收藏0
    • Flask Web Development —— Web表单(下)

      摘要:局部变量用于保存从表单中接收到的名字,初始化时变量为。在语句中,这个名字被赋值给局部变量且表单域的数据属性通过赋值为空字符串而被清除。示例重定向和用户会话在上一个版本中,局部变量用于保存用户在表单中输入的姓名。 4、视图函数中的表单操作 在新版本的hello.py中,index()视图函数渲染表单并接收其数据。示例4-4展示更新后的index()视图函数。 示例4-4. hello...

      yeooo 评论0 收藏0

    发表评论

    0条评论

    最新活动
    阅读需要支付1元查看
    <