资讯专栏INFORMATION COLUMN

FlaskWeb开发读书笔记之jinja2模板

tangr206 / 496人阅读

摘要:注模板包含不存在此问题。在模板中,使用过滤器显式地标记一个字符串为安全的临时地完全禁用自动转义系统。通过在声明中直接添加或,当前的上下文可以传递到模板,而且不会自动禁用缓存。

官网:http://jinja.pocoo.org/docs/dev/
中文文档:http://docs.jinkan.org/docs/j...
当前版本2.8

安装:pip install Jinja2
Flask 使用 Jinja 2 作为模板引擎。当然,你也可以自由使用其它的模板引擎,但运行 Flask 本身仍然需要 Jinja2 依赖 ,这对启用富扩展是必要的,扩展可以依赖 Jinja2 存在。
Jinja 2 默认配置如下:

所有扩展名为 .html 、 .htm 、 .xml 以及 .xhtml 的模板会开启自动转义

模板可以利用 {% autoescape %} 标签选择自动转义的开关。

Flask 在 Jinja2 上下文中插入了几个全局函数和助手,另外还有一些目前默认的值

Jinja2 内部使用 Unicode

自动转义,防止XSS攻击

标准上下文

下面的全局变量默认在 Jinja2 模板中可用:

config:当前的配置对象 (flask.config)

request当前的请求对象 (flask.request)。当模版不是在活动的请求上下文中渲染时这个变量不可用。

session当前的会话对象 (flask.session)。当模版不是在活动的请求上下文中渲染时这个变量不可用。

g请求相关的全局变量 (flask.g)。当模版不是在活动的请求上下文中渲染时这个变量不可用。

url_for():flask.url_for() 函数

get_flashed_messages():flask.get_flashed_messages() 函数

问题:Jinja 上下文行为与模板导入import

这些变量被添加到了请求的上下文中,而非全局变量。
区别在于,他们默认不会在导入(import)模板的上下文中出现。这样做,一方面是考虑到性能,另一方面是为了让事情显式透明。注:模板包含include不存在此问题。
这对你来说意味着什么?如果你想要导入一个需要访问请求对象的宏,
有两种可能的方法:

显式地传入请求或请求对象的属性作为宏的参数。

使用with context导入宏。

with context导入的方式如下:
{% from "_helpers.html" import my_macro with context %}


{% block title %}{% endblock %}

简单使用

>>> from jinja2 import Template
>>> template = Template("Hello {{ name }}")
>>> template.render(name="John Doe")
u"Hello John Doe!"
基础

Jinja2 使用一个名为 Environment 的中心对象。这个类的实例用于存储配 置、全局对象,并用于从文件系统或其它位置加载模板。
配置 Jinja2 为你的应用加载文档的最简单方式看起来大概是这样:

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader("yourapplication", "templates"))

获取并渲染模板:

template = env.get_template("mytemplate.html")
#用若干变量来渲染它,调用 render() 方法:
print template.render(the="variables", go="here")
变量过滤器:
hello,{{ name|capitalize }}

常用变量过滤器列表:

safe 渲染时不进行html转义(默认会进行转义)。

capitalize 把值得首字母大写,其余字符转小写

lower

upper

title

trim

striptags 渲染之前把值中所有的HTML标签都删掉

内置过滤器清单

自定义过滤器

自定义过滤器只是常规的 Python 函数,过滤器左边作为第一个参数,其余的参数作 为额外的参数或关键字参数传递到过滤器。

例如在过滤器 {{ 42|myfilter(23) }} 中,函数被以 myfilter(42, 23) 调 用。这里给出一个简单的过滤器示例,可以应用到 datetime 对象来格式化它们:

def datetimeformat(value, format="%H:%M / %d-%m-%Y"):
    return value.strftime(format)

你可以更新环境上的 filters 字典来把它注册到模板环境上:

environment.filters["datetimeformat"] = datetimeformat

在模板中使用如下:

written on: {{ article.pub_date|datetimeformat }}
publication date: {{ article.pub_date|datetimeformat("%d-%m-%Y") }}

除了上面提到的原生方式注册,在Flask中如果你要在 Jinja2 中注册你自己的过滤器,你还有2种方法。你可以把它们手动添加到应用的 jinja_env 或者使用 template_filter() 装饰器。
下面两个例子作用相同,都是反转一个对象:

#第一种
@app.template_filter("reverse")
def reverse_filter(s):
    return s[::-1]
#第二种
def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters["reverse"] = reverse_filter
控制自动转义

有三种可行的解决方案:

在传递到模板之前,用 Markup 对象封装 HTML字符串。一般推荐这个方法。

在模板中,使用 |safe 过滤器显式地标记一个字符串为安全的 HTML {{ myvariable|safe }}

临时地完全禁用自动转义系统。{% autoescape false %}
在模板中禁用自动转义系统,可以使用 {%autoescape %} 块:

{% autoescape false %}
    

autoescaping is disabled here

{{ will_not_be_escaped }} {% endautoescape %}

上下文处理器

Flask 上下文处理器自动向模板的上下文中插入新变量。上下文处理器在模板渲染之前运行,并且可以在模板上下文中插入新值。
上下文处理器是一个返回字典的函数,这个字典的键值最终将传入应用中所有模板的上下文:

@app.context_processor
def inject_user():
    return dict(user=g.user)

上面的上下文处理器使得模板可以使用一个名为 user ,值为 g.user 的变量。 不过这个例子不是很有意思,因为 g 在模板中本来就是可用的,但它解释了上下文处理器是如何工作的。
变量不仅限于值,上下文处理器也可以使某个函数在模板中可用(由于 Python 允许传递函数):

@app.context_processor
def utility_processor():
    def format_price(amount, currency=u"€"):
        return u"{0:.2f}{1}.format(amount, currency)
    return dict(format_price=format_price)

上面的上下文处理器使得 format_price 函数在所有模板中可用:

{{ format_price(0.33) }}

你也可以构建 format_price 为一个模板过滤器(见 注册过滤器 ), 但这展示了上下文处理器传递函数的工作过程。

模板语法

这里有两种分隔符: {% ... %} 和{{ }} 。前者用于执行诸如 for 循环 或赋值的语句,后者把表达式的结果打印到模板上。
要把模板中的部分注释掉,默认使用 {# ... #} 注释语法。
true,false,none,这一点与python内置有点区别

变量:
Jinja2能够识别所有类型的变量,例如列表,字典和对象。如下:

{{ mydict["key"] }}
{{ mylist[3] }}
{{ mylist[myintvar] }}
{{ myobj.somemethod() }}

算术,比较,逻辑语法均和python相同

流程控制:

1、条件控制:

{% if user %}
hello {{ user }}!
{% else %}
hello, world
{% endif %}

2、for循环:

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

在一个 for 循环块中你可以访问这些特殊的变量:

loop.index 当前循环迭代的次数(从 1 开始)

loop.index0 当前循环迭代的次数(从 0 开始)

loop.revindex 到循环结束需要迭代的次数(从 1 开始)

loop.revindex0 到循环结束需要迭代的次数(从 0 开始)

loop.first 如果是第一次迭代,为 True 。

loop.last 如果是最后一次迭代,为 True 。

loop.length 序列中的项目数。

loop.cycle 在一串序列间期取值的辅助函数。见下面的解释。

宏支持

宏类似于函数。如:

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

    为了重复使用宏,可以将宏定义保存在多带带的文件中,然后导入:

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

    此外你也可以从模板中导入名称到当前的命名空间:

    {% from "forms.html" import input as input_field, textarea %}
    
    模板继承
    
    
      {% block head %}
      {% block title %}{% endblock %}
      {% endblock %}
    
    
      {% block body %}
      {% endblock %}
    
    
    

    上述定义了三个块(block):head、title、body,衍生模板可以修改这三个块

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

    hello

    {% endblock %}

    在extends指令之后,基模板中的3个块被重新定义,模板引擎会将其插入适当位置。super()可以用来获取父模板原来的内容。

    如果你想要多次打印一个块,无论如何你可以使用特殊的 self 变量并调用与块同名 的函数:

    {% block title %}{% endblock %}
    

    {{ self.title() }}

    {% block body %}{% endblock %}
    嵌套块和作用域

    嵌套块可以胜任更复杂的布局。而默认的块不允许访问块外作用域中的变量:

    {% for item in seq %}
        
  • {% block loop_item %}{{ item }}{% endblock %}
  • {% endfor %}

    这个例子会输出空的 < li> 项,因为 item 在块中是不可用的。其原因是,如果 块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。
    从 Jinja 2.2 开始,你可以显式地指定在块中可用的变量,只需在块声明中添加 scoped 修饰,就把块设定到作用域中:

    {% for item in seq %}
        
  • {% block loop_item scoped %}{{ item }}{% endblock %}
  • {% endfor %}

    当覆盖一个块时,不需要提供 scoped 修饰。

    包含

    include 语句用于包含一个模板,并在当前命名空间中返回那个文件的内容渲 染结果:

    {% include "header.html" %}
        Body
    {% include "footer.html" %}
    
    导入与包含的上下文行为

    默认下,每个**包含**的模板会被传递到当前上下文,而**导入**的模板不会。 这样做的原因 import会被缓存,因为导入量经常只作容纳宏的模块。并且默认下导入的 模板不能访问当前模板中的非全局变量。这当然也可以显式地更改。通过在 import/include 声明中直接添加 with context 或 without context ,当前的上下文可以传递到模板,而且不会 自动禁用缓存。

    {% from "forms.html" import input with context %}
    {% include "header.html" %}
    
    变量定义与赋值

    在代码块中,你也可以为变量赋值。在顶层的(块、宏、循环之外)赋值是可导出的,即 可以从别的模板中导入。
    赋值使用 set 标签,并且可以为多个变量赋值:
    {% set navigation = [("index.html", "Index"), ("about.html", "About")] %}
    {% set key, value = call_something() %}

    不进行Jinjia2语法解释
    {% raw %}
    {%blahblahblah%}
    {% endraw %}
    
    自定义错误页面
    @app.errorhandler(404)
    def page_not_found(e):
        return render_template("404.html"),404
    
    
    链接

    url_for("index")输出"/"
    url_for("index",_external=True)输出http://localhost:5000/

    静态文件

    特殊路由/static/< filename>
    url_for("static",filename="css/style.css") 输出http://localhost:5000/static/...
    默认设置下,Flask在程序目录中名为static的子目录中寻找静态文件。

    内置工具函数

    http://docs.jinkan.org/docs/j...

    国际化

    _(" ")

    {{ _("Hello World!") }}
    With 语句

    如果应用启用了 With 语句 ,将允许在模板中使用 with 关键 字。
    这使得创建一个新的内作用域。这个作用域中的变量在外部是不可见的。
    With 用法简介:

    {% with %}
        {% set foo = 42 %}
        {{ foo }}           foo is 42 here
    {% endwith %}
    foo is not visible here any longer
    使用Flask-Moment本地化日期和时间

    详情请参考

    使用Flask-Bootstrap

    详情参考

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

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

    相关文章

    • [叁]Flask web开发:模板

      摘要:使用真实值替代变量,再返回最终得到的响应字符串,这一过程成为渲染。渲染模板渲染模板提供的函数把模板引擎集成到了程序中。随后的参数都是键值对,表示模板中变量对应的真实值。程序现在使用的模板继承自不是直接继承自的基模板。 本系列笔记是我阅读Miguel Grinberg的《Flask Web Development》的笔记,标题与书本同步。希望通过记录技术笔记的方式促进自己对知识的理解。 ...

      mochixuan 评论0 收藏0
    • Flask 源码阅读笔记 开篇

      摘要:官方示例第一行类对象,这个无需解释。请求对象的端点请求视图函数的参数通过源码的注释我们可以知道,都只是对库的进行了一层包装并加入一些属性。接下来会有更多关于和相关文章放出来,敬请期待参考文档项目源码版本注释版 Flask 是一个 Python 实现的 Web 开发微框架, 有丰富的生态资源。本文从一段官方的示例代码通过一步步打断点方式解释 Flask 内部的运行机制,在一些关键概念会...

      mikyou 评论0 收藏0
    • django中的配置文件

      摘要:默认的,及使用它的号数据库此处使用号数据库,在客户端查看记得切换数据库存储在本机内存中,比数据库的方式读写快很多默认的配置项,采用号库。状态保持的配置项,采用号库。使用名为的配置项存储数据。配置完成后运行程序,测试结果。 1.配置开发环境当进入虚拟环境,通过django_admin创建一个项目后,会在项目同名目录生成一个setting.py文件。而实际项目过程中会有不同的环境,如开发环境、生...

      番茄西红柿 评论0 收藏0
    • django中的配置文件

      摘要:默认的,及使用它的号数据库此处使用号数据库,在客户端查看记得切换数据库存储在本机内存中,比数据库的方式读写快很多默认的配置项,采用号库。状态保持的配置项,采用号库。使用名为的配置项存储数据。配置完成后运行程序,测试结果。 1.配置开发环境当进入虚拟环境,通过django_admin创建一个项目后,会在项目同名目录生成一个setting.py文件。而实际项目过程中会有不同的环境,如开发环境、生...

      williamwen1986 评论0 收藏0

    发表评论

    0条评论

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