【Flask学习笔记】模板(二)

阅读更多

flask 使用 jinjia2 模板引擎,为了便于使用,已经集成到 render_template 函数中,可以直接调用。模板引擎实现对模板的渲染,就是根据上下文,对模板中的占位变量,用真实值替换,形成最终的响应文件。

默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板。

 

(一)模板的调用

demo.py文件代码如下:

from flask import Flask
from flask import render_template
app = Flask(__name__)

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

注意:render_template中是包含 .html 后缀的完整文件名 

index.html文件代码如下:



    
    


hello world!

 执行demo.py后,浏览器访问地址:http://127.0.0.1:5000/,页面显示“hello world”。

这就完成了简单的一次模板调用。

(二)模板的传参

#模板传参
@app.route('/user/')
def user(xiao):
    return render_template("xiao.html",xiao=xiao)

  第一个参数是模板的名称,然后是 键/值 对,xiao=xiao左边表示模板中的占位符,右边是当前视图中的变量。意思是,将当前视图中变量xiao的值,赋值给模板中名为xiao的占位符,用于渲染。

xiao.html代码如下:



    
    


传递参数:{{ xiao }}

 执行后,浏览器访问地址:http://127.0.0.1:5000/user/,其中“”为变量,需要手动赋值。

若是:http://127.0.0.1:5000/user/123,则显示“传递参数:123”

若是:http://127.0.0.1:5000/user/abc,则显示“传递参数:abc”

 

(三)模板的变量传参

@app.route('/test')
def hello_world():
    centent="调用的hello_world()函数里面的centent"
    return render_template("test.html",centent=centent)

 第一个参数是模板的名称,然后是 键/值 对,centent=centent左边表示模板中的占位符,右边是当前视图中的变量。意思是,将当前视图中变量centent的值,赋值给模板中名为centent的占位符,用于渲染。

test.html代码如下:



    
    


   调用的参数为: {{ centent }}

  执行后,浏览器访问地址:http://127.0.0.1:5000/user/test,返回结果为:"调用的参数为: 调用的hello_world()函数里面的centent"

  • 表示

{{ name }}

占位符,告诉模板引擎,这个位置的值从渲染模板时传递的数据字典中获取

  • 支持的变量类型

支持所有类型,字符串、整型、列表、字典 ......

  • 修改显示样式

通过使用过滤器,可以定制 变量的值 显示的效果,比如 大小写。{{ name | 过滤器 }}

过滤器列表

  • 模板变量

在模板中设置模板变量

 

{% set name = 'john' %}

 

(四)模板的相对复杂的对象传递

 

 

Jinja2变量过滤器
过滤器名 说  明
safe 渲染值时不转义
capitalize 把值得首字母转为大写,其它字母转为小写
lower 把值转换成小写形式
upper 把值转换成大写形式
title 把值中每个单词的首字母转换成大写
trim 把值得首尾空格去掉
striptags 渲染之前把值中所有的HTML标签都删掉

safe 过滤器值得特别说明一下。默认情况下,出于安全考虑,Jinja2 会转义所有变量。例

如,如果一个变量的值为 '

Hello

' ,Jinja2 会将其渲染成 '<h1>Hello</

h1>' ,浏览器能显示这个 h1 元素,但不会进行解释。很多情况下需要显示变量中存储

的 HTML 代码,这时就可使用 safe 过滤器。

千万别在不可信的值上使用 safe 过滤器,例如用户在表单中输入的文本。

完整的过滤器列表可在 Jinja2 文档(http://jinja.pocoo.org/docs/templates/#builtin-filters)中

查看。

新建modes.py文件,代码如下:

#创建一个User类,用来存放users
class User(object):
    #定义两个字段,一个user_id,一个user_name
    def __init__(self,user_id,user_name):

        self.user_id=user_id
        self.user_name=user_name

 demo.py文件代码如下:

#coding:utf-8
from flask import Flask
from flask import render_template
from modes import  User
app = Flask(__name__)

#传递一个name对象
@app.route('/name')
def name():
    user=User(1,"xiaojingjing")
    return render_template("user_index.html",user=user)

if __name__ == '__main__':
    app.run()

 user_index.html文件代码如下:



    
    


   你好! {{ user.user_name }}

 执行后,浏览器访问地址:http://127.0.0.1:5000/name,返回结果为:"你好! xiaojingjing"

(五)控制语句  if  else 判断

 

demo.py文件代码如下:

#控制语句,if else 判断
@app.route('/user_name/')
def user_name(user_id):
    user=None
    if int(user_id)==1:
        user=User(1,'xiaojingjing')
    # else:
    #     return "Sorry,no this user"
    return render_template("user_id.html",user=user)

 user_id.html文件代码如下:



    
    


{% if user %}
你好,{{ user.user_name }}!
{% else %}
    no this user
{% endif %}

  执行后,浏览器访问地址:http://127.0.0.1:5000/user_name/1,返回结果为:"你好! xiaojingjing"

 执行后,若浏览器访问地址:http://127.0.0.1:5000/user_name/2,返回结果为:"no this user"

 

(六)控制语句 for循环

demo.py文件代码如下:

#控制语句,for循环
@app.route('/user_list')
def user_list():
    users=[]
    for i in range(1,11):
        user=User(i,"小白"+str(i))
        users.append(user)
    return  render_template("user_list.html",users=users)

 user_list.html文件代码如下:



    
    


{% for user in users %}
    {{ user.user_id }}--{{ user.user_name }}
{% endfor %}

   执行后,浏览器访问地址:http://127.0.0.1:5000/user_list,

返回结果为:

"1--小白1
2--小白2
3--小白3
4--小白4
5--小白5
6--小白6
7--小白7
8--小白8
9--小白9
10--小白10"

 

(七)继承

如果多个页面的大部分内容相同,可以定义一个母模板,包含相同的内容,然后子模板继承内容,并根据需要进行部分修改

base.html,母模板,其中,用{% block title %}...{% endblock %}定义了可以由子模板替换的区域,title是区块的名称,可以有多个区块

{% block title %}Hello{% endblock %}

 在子模板中,声明继承的母模板,然后用{% block title %}...{% endblock %}指定替换哪个区块的内容,并填入自己的内容。子模板中没有指定的区块,默认使用母模板的内容

{% extends "base.html" %}

{% block title %}john{% endblock %}

 如果希望能够保留母版的内容,并添加新内容,可以使用super()

{% extends "base.html" %}

{% block title %}
    {{ super() }}
    john
{% endblock %}

 PS:模板里面,不能同时有两个{% extends " " %}语句,即使另一个被注释了也不行

如果多个网页中都有一段内容相同,可以将相同的内容放入一个文件中comments.html,通过include导入

{% include 'comments.html' %}

 

首先,创建一个基类

base.html文件,代码如下:



    
    


top部分

{% block content %} {% endblock %}

底部部分

 one_base.html文件,代码如下:

{% extends "base.html" %}
{% block content%}
    这是第一页
{% endblock %}

 two_base.html文件,代码如下:

{% extends "base.html" %}
{% block content%}
    这是第二页
{% endblock %}

 然后到demo再新定义两个路由,代码如下:

#模板的继承

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

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

 执行后,浏览器访问地址:“http://127.0.0.1:5000/one_base” 和“http://127.0.0.1:5000/two_base”

 

--------------待补充:

宏:macro...endmacro

类似函数

 

定义一个宏,指定宏的名称、参数,调用

 

{% macro x(y) %}
    ...
{% endmacro %}

{{ x(y) }}

 如果需要在多个模板中复用,可以将宏的定义放入一个文件,‘macro.html’

{% macro x(y) %}
    ...
{% endmacro %}

 然后导入使用

import 'macro.html' as macro

{{ macro.x(y) }}

 

 

bootstrap

Bootstrap是 Twitter 开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代 Web 浏览器。

一个名为Flask-Bootstrap的 Flask 扩展, 可以简化在程序中集成 Bootstrap 的过程。

安装:

pip install flask-bootstrap

 初始化

从 flask.ext 命名空间中导入,然后把 程序实例传入构造方法进行初始化。

run.py

 

from flask.ext.bootstrap import Bootstrap 
# ...
bootstrap = Bootstrap(app)

 初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。 这个模板利用 Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中 就有用来引入 Bootstrap 的元素。

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}
{% block navbar %}

{% endblock %}
{% block content %} 
{% endblock %}

 Jinja2 中 的 extends 指 令 从 Flask-Bootstrap 目录中导入 bootstrap/base.html, 从而实现模板继承。Flask-Bootstrap 中的基模板提供了一个网页框架,引入了 Bootstrap 中的所有 CSS 和 JavaScript 文件

virtualenv 环境中,目录为lib/python2.7/site-packages/flask_bootstrap/templates/bootstrap/

 

基模板中定义了可在衍生模板中重定义的块。block 和 endblock 指令定义的块中的内容可添加到基模板中。

Bootstrap 官方文档是很好的学习资源,有很多可以直接复制粘贴的示例。

 

自定义错误页面

像常规路由一样,Flask 允许程序使用基于模板的自定义错误页面。最常见的错误代码有两个:404,客户端请求未知页面或路由时显示;500,有未处理的异常时显示。

自定义错误页面,代码如下:

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

 和视图函数一样,错误处理程序也会返回响应。它们还返回与该错误对应的数字状态码。 返回指定的数字状态码似乎没有什么用 

 

 

url_for 生成连接

模板中可能有去往多个不同页面的链接,例如导航条。

在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的 依赖关系(hardcode)。如果修改 路由、视图 的绑定关系, 模板中的链接可能会失效。

为了避免这些问题,Flask 提供了url_for()辅助函数,它可以使用程序URL映射中保存的信息,根据视图名称生成 URL。

 

例如,对于下面的视图

@app.route('/')
def index():
    return '

Hello World!

'

 调用 url_ for('index')得到的结果是/。调用url_for('index', _external=True)返回的则是绝对地址,是http://localhost:5000/

在程序内(模板、视图中)生成连接程序内不同路由的链接时,使用相对地址就足够了,浏览器、程序能够根据当前的 URL 补全。但如果要在浏览器以外生成链接,例如在确认邮件中的链接,则必须使用绝对地址,否则谁也不知道前缀是什么。

使用url_for()生成链接时,将动态部分作为关键字参数传入。例如,

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

 

url_for ('user', name='john', _external=True)

 返回结果是:http://localhost:5000/user/john

 

默认 _external 为 False,表示生成相对路径;为 True 时,表示生成绝对路径

函数能将任何额外参数添加到查询字符串中。例如,

url_for('user', name='john', page=2)的返回结果是/user/john/?page=2

 

对于多层的模板结构,render_template 函数中需要添加从templates目录下文件夹开始的路径信息,render_template('main/index.html'),结构为templates/main/index.html,url_for() 需要用.隔开目录,url_for('main.index.html')

 

 

你可能感兴趣的:(Flask,模板,模板继承)