模板引擎

模板引擎

说明:

模板文件就是按照特定规则书写的一个负责展示效果的HTML文件 模板引擎就是提特定规则的解释和替换的工具

Jinja2

flask的模板引擎使用的就是Jinja2的模板引擎 它是由flask核心开发组成员开发的

一、模板的使用

(1) 准备工作 目录结构
project/
	manage.py   项目启动控制文件
    templates/  模板文件的目录
(2) 渲染模板文件

在templates模板目录下 创建一个模板文件 hello.html 内容如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>Lucky老师  你好帅啊 好骚气啊</h4>
</body>
</html>
(3) 创建hello视图函数 代码如下
# 创建hello的路由地址
@app.route('/hello/')
def hello():
    return 'hello'
(4) 渲染模板的方法

导入:

from flask import Flask,render_template,render_template_string
  1. 渲染模板

    render_template(模板名称,**context)

  2. 返回一段渲染的html代码

    render_template_string(渲染的HTML代码,**context)

使用实例:

# 创建hello的路由地址
@app.route('/hello/')
def hello():
    # 渲染模板文件  hello.html
    # return render_template('hello.html')
    return render_template_string('<p style="font-size:20px;color:yellow;">lucky老师你好帅 我想和你生猴子</p>')
(5) 使用变量

简介:

  1. 视图传递给模板的数据

  2. 遵循标识符的命名规则

  3. 语法格式

    {{ var }}

  4. 如果模板使用的变量不存在 则插入的为空白字符

实例:

manage.py

@app.route('/hello/')
def hello():
    return render_template('hello.html',name='lucky',age=18,sex='男',hobby='写代码和学习')

hello.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h4>我叫:{{ name }} 我今年{{ age }}岁了  我的性别是{{ sex }} 我的爱好是{{ hobby }} 希望台上的女嘉宾你可以给我留灯</h4>
</body>
</html>

二、标签

格式:

{% tag %}

作用:

  1. 在输出中创建文本
  2. 控制逻辑和循环
(1) 流程控制 之 if

主体结构:

{% if ... %}
	...
{% elif ... %}
	...
{% else %}
	...
{% endif %}

实例:

{% if grade >= 90 %}
    成绩为{{ grade }} 优秀
{% elif grade >= 80 %}
    成绩为{{ grade }} 良
{% elif grade >= 60 %}
    成绩为{{ grade }} 合格
{% else %}
    成绩为{{ grade }} 不合格
{% endif %}
(2) 流程控制之 for

主题结构:

{% for item in Iterable %}
	...
{% else %}
	...
{% endfor %}

实例:

<h4>for循环的使用</h4>
<ul>
    {% for i in myRange %}
        <li>{{ i }}</li>
    {% else %}
        <p>该变量不存在</p>
    {% endfor %}
</ul>

迭代字典

<h4>迭代字典</h4>
{% for key,value in infoDict.items() %}
    <p>key---->{{ key }}  value----->{{ value }}</p>
{% endfor %}
在for循环中还包含一下变量 用来获取当前的遍历状态
变量描述
loop.index当前迭代的索引 从1开始
loop.index0当前迭代的索引 从0开始
loop.first是否为第一次迭代 返回True/False
loop.last是否为最后一次迭代 返回True/False
loop.length迭代的长度

实例:

<h4>获取迭代时的状态</h4>
<ul>
    {% for i in myRange %}
        <li>{{ loop.index }}----{{ loop.index0 }}-----{{ loop.first }}-----{{ loop.last }}-------{{ loop.length }}</li>
    {% endfor %}
</ul>

注意:

  1. for循环搭配的else 只有当迭代的变量不存在的时候 才会执行else
  2. 循环不可以使用continue和break 来控制循环的执行

三、注释标签(多行注释)

作用:

  1. 代码调试
  2. 简介说明

格式:

{# 这是一个注释 #}

注意:

注释的代码都不会在浏览器的HTML页面中显示出来

四、文件包含 include

概述:

include语句 可以把一个模板引入到另外一个模板中 类似于把一个不安的代码 copy到另外一个模板的指定位置中 实现模板代码的复用

实例:

head.html

<nav>我是头部</nav>

footer.html

<footer>底部</footer>

test_include.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            padding:0;
            margin: 0;

        }
        nav{
            width:100%;
            height: 40px;
            background-color: #000;
            color: #fff;
        }
        footer{
            width:100%;
            height: 100px;
            background-color: orange;
            position: absolute;
            bottom:0;
        }
    </style>
</head>
<body>
{% include 'common/head.html' %}
<div>我是中间主体部分</div>
{% include 'common/footer.html' %}
</body>
</html>

注意:

导入的文件的代码一定是当前需要的 不要添加任何其它的代码 包括主体结构 否则会将当前页面的所有代码包含进来

五、宏 macro

概述:

类似于我们python的函数 可以封装一段特定功能的HTML代码段

主体结构:

# 定义宏
{% amcro 宏的名称([参数[参数...]]) %}
	...
{% endmacro %}
# 调用宏
{{ 宏名称([参数[参数...]]) }}
(1) 宏的简单使用
{% macro test() %}
    当你调用宏的时候就会看到我了
{% endmacro %}
{{ test() }}
{{ test() }}
(2) 宏的传参使用
<h4>测试宏的传参的使用</h4>
{#{% macro test_arg(name,age) %}#}
{#形参默认值#}
{% macro test_arg(name='lucky',age=18) %}
    <p>我叫:{{ name }} 我今年{{ age }}岁了</p>
{% endmacro %}
{#调用不传实参 正常使用#}
{#{{ test_arg() }}#}
{#传实参#}
{#{{ test_arg('lucky',18) }}#}
{{ test_arg('张三') }}
(3) 宏的导入

common/public_macro.html

{% macro test_arg(name='lucky',age=18) %}
    <p>我叫:{{ name }} 我今年{{ age }}岁了</p>
{% endmacro %}

导入使用:

<h4>测试宏的导入使用</h4>
{#第一种导入方式#}
{% from 'common/public_macro.html' import test_arg %}
{{ test_arg() }}
{#起别名#}
{% from 'common/public_macro.html' import test_arg as my_tag %}
{{ my_tag() }}
{% import 'common/public_macro.html' as public_macro %}
{{ public_macro.test_arg('张三') }}

注意:

不能在宏定义的上方去调用

六、模板继承

flask中的模板可以继承 通过继承可以把模板中许多重复出现的元素抽取出来 放在父模板中 并且父模板通过定义 block给子模板开一个口 子模板根据需要 在实现这个block

用到的标签

  • 继承

    extends

  • 替换

    block

实例:

创建commone/base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Title{% endblock %}</title>
    <style>
        *{
            padding: 0;
            margin: 0;
            list-style: none;
        }
        ul,footer{
            width: 100%;
            background-color: #000;
        }
        li{
            width:150px;
            height: 30px;
            text-align: center;
            line-height: 30px;
            color: #fff;
        }
        footer{
            height: 30px;
            position: absolute;
            bottom:0;
            color:#fff;
        }

    </style>
</head>
<body>
<nav>
    <ul>
        <li>首页</li>
        <li>首页</li>
    </ul>
</nav>
<div class="con">
    {% block con %}
    <p>我是显示主题内容的位置</p>
    {% endblock %}
</div>
<footer>
    我是底部栏
</footer>
</body>
</html>
index.html集成common/base.html的模板
{% extends 'common/base.html' %}
{% block title %}
首页
{% endblock %}
{% block con %}
    {{ super() }}
<h2>我是index模板替换的内容</h2>
{% endblock %}
<p>在block之外的内容不会显示出来</p>

路由和视图函数

# 测试base模板使用的路由地址
@app.route('/test_base/')
def test_base():
    return render_template('common/base.html')


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

注意:

  1. 在父模板中如果添加了block 在子模板中没有进行替换 则正常显示 没有任何影响

  2. 在子模板进行block替换的位置以外的地方 添加任何代码都不会被显示出来

  3. 如果在子模板中进行了父模板某个block内容的替换 如果想将替换的内容在显示出来 则调用变量 super()方法

    {{ super() }}

  4. 父模板中如果存在的block越多 那么就证明父模板越灵活

七、flask-bootstrap扩展库

安装:

pip install flask-bootstrap

使用:

from flask import Flask,render_template
from flask_script import Manager
from flask_bootstrap import Bootstrap


app = Flask(__name__)
# 实例化对象
Bootstrap(app)
manager = Manager(app)
查看flask-bootstrap扩展库的base.html
{% block doc -%}
<!DOCTYPE html>
<html{% block html_attribs %}{% endblock html_attribs %}>
{%- block html %}
  <head>
    {%- block head %}
    <title>{% block title %}{{title|default}}{% endblock title %}</title>

    {%- block metas %}
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    {%- endblock metas %}

    {%- block styles %}
    <!-- Bootstrap -->
    <link href="{{bootstrap_find_resource('css/bootstrap.css', cdn='bootstrap')}}" rel="stylesheet">
    {%- endblock styles %}
    {%- endblock head %}
  </head>
  <body{% block body_attribs %}{% endblock body_attribs %}>
    {% block body -%}
    {% block navbar %}
    {%- endblock navbar %}
    {% block content -%}
    {%- endblock content %}

    {% block scripts %}
    <script src="{{bootstrap_find_resource('jquery.js', cdn='jquery')}}"></script>
    <script src="{{bootstrap_find_resource('js/bootstrap.js', cdn='bootstrap')}}"></script>
    {%- endblock scripts %}
    {%- endblock body %}
  </body>
{%- endblock html %}
</html>
{% endblock doc -%}

每个block的作用

block说明
doc整个HTML文档
htmlhtml内部所有代码
headhead标签
titletitle标签
styles引入css样式
metas一组meta标签
bodybody标签
navbar用户自定义当好条
content用户自定义内容
scripts用户定义的js

简单使用flask-bootstrap的base

{% extends 'bootstrap/base.html' %}
{% block title %}
    boot_base
{% endblock %}
{% block content %}
    继承了flask_bootstrap的base模板的子模板
{% endblock %}

路由和视图函数

# 测试bootstrap的基础模板
@app.route('/test_boot_base/')
def test_boot_base():
    return render_template('common/boot_base.html')

定义项目基础模板

概述:

一个项目中 很多页面都相似 只有细微差别 如果每个都定制 那么就会有大量的重复的代码 为了简化这种工作 我们通常为项目定制一个基础模板(base) 让它集成子bootstrap的基础模板 其它页面集成该基础模板 只需稍微定制即可

实例:

{% extends 'bootstrap/base.html' %}
{% block title %}
    boot_base
{% endblock %}
{% block navbar %}
<nav class="navbar navbar-inverse" style="border-radius: 0">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <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="#">
          <span class="glyphicon glyphicon-fire" aria-hidden="true"></span>
      </a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">首页 <span class="sr-only">(current)</span></a></li>
        <li><a href="#">发表博客</a></li>
      </ul>

      <ul class="nav navbar-nav navbar-right">
          <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Search</button>
      </form>
        <li><a href="#">登录</a></li>
        <li><a href="#">注册</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">个人中心<span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
{% endblock %}
{% block content %}
<div class="container">
    {% block page_content %}
      继承了flask_bootstrap的base模板的子模板
    {% endblock %}
</div>
{% endblock %}

配置家在本地bootstrap的样式 不再从网络获取

app = Flask(__name__)
# 加载使用本地的样式
app.config['BOOTSTRAP_SERVE_LOCAL'] = True
# 实例化对象
Bootstrap(app)
manager = Manager(app)

八、错误页面定制

(1) 添加视图函数
# 错误状态码捕获
@app.errorhandler(404)
def page_not_found(e):
    return render_template('error.html',title="404_NOT_FOUND",info="您访问的地址被外星人抓走了...")


@app.errorhandler(500)
def server_error(e):
    return render_template('error.html',title="500_SERVER_ERROR",info='您的访问太热情了 请稍后访问...')
(2) 错误模板
{% extends 'common/boot_base.html' %}
{% block title %}
{{ title }}
{% endblock %}
{% block page_content %}
<div class="alert alert-danger alert-dismissible" role="alert">
  <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
  <strong>{{ title }}</strong> {{ info }}
</div>
{% endblock %}

九、模板中url_for的使用

概述:

根据视图函数构造路由地址

  1. 根据视图函数名反向构造路由地址,路由需要的直接构造,多出来的参数以GET传递

    url_for('var', name='lucky', pwd='123456')
    

    /var/?name=lucky&pwd=123456,不完整,没有主机和端口

  2. 若需要构造完整的外部链接,需要添加_extenal=True的参数

    url_for('var', name='xiaoming', pwd='123456', _external=True)
    

    http://127.0.0.1:5000/var/?name=xiaoming&pwd=123456

  3. 通常网站中的点击链接都是使用url_for构造的,如:

    <li><a href="{{ url_for('register') }}">注册</a></li> #register 为视图函数名
    

视图函数代码

# 一个测试的路由地址
@app.route('/test/')
def test():
    return '测试路由地址'


# 一个测试的路由地址 带传参的
@app.route('/test2/<arg>/')
def test2(arg):
    return '测试路由地址参数arg值为{}'.format(arg)

模板代码

<dl>
    <dt>相对地址</dt>
    <dd>{{ url_for('test') }}</dd>
    <dt>绝对地址</dt>
    <dd>{{ url_for('test',_external=True) }}</dd>
    <dt>绝对地址get传参</dt>
    <dd>{{ url_for('test',name='lucky',age=18,_external=True) }}</dd>
    <dt>绝对地址路由传参</dt>
    <dd>{{ url_for('test2',arg='arg',_external=True) }}</dd>
    <dt>绝对地址路由传参并添加到超链接中</dt>
    <dd><a href="{{ url_for('test2',arg='arg',_external=True) }}">test2</a></dd>
</dl>

注意:

如果构造的视图函数在某个蓝本中 那么在模板中构造路由地址和视图函数中一样

{{ url_for(‘蓝本名称.视图函数名’) }}

十、加载静态资源

静态资源文件?

css js img 统称为静态资源文件

(1) flask框架中静态资源默认为目录为static 项目目录结构为
project/
	templates/	模板目录
	static/	静态资源目录
		img/
			timg.jpg
		css/
		js
	manage.py 启动文件
(2) 加载图片资源

实例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="icon" href="{{ url_for('static',filename="img/timg.jpeg") }}">
</head>
<body>
<h2>首页</h2>
<h4>升仕310x摩托车</h4>
<img src="{{ url_for('static',filename='img/timg.jpeg',_external=True) }}" alt="">
</body>
</html>

十一、视图传递多个参数

(1) 使用全局变量g

导入:

from flask import g

视图函数中

@app.route('/')
def index():
    g.name = 'lucky'
    g.age = 18
    return render_template('index.html')

模板中

<h4>测试传递多个参数</h4>
<p>{{ g.name }}</p>
<p>{{ g.age }}</p>
(2) 使用**locals()

视图函数中

@app.route('/')
def index():
    name = 'lucky'
    age = 18
    print(locals())
    return render_template('index.html',**locals())

模板中

<p>{{ name }}</p>
<p>{{ age }}</p>
(3) 使用字典传参

视图函数中

@app.route('/')
def index():
    return render_template('index.html',**{'name':'lucky','age':18})

模板中

<p>{{ name }}</p>
<p>{{ age }}</p>
(4) 原始传参
@app.route('/')
def index():
    return render_template('index.html',name='lucky',age=18)

十二、过滤器

概述:

过滤器相当于是一个python函数 把当前变量传入到过滤器中 过滤器根据自己的功能进行过滤 并返回相应的值 在输出到模板

Jinja2中内置了许多过滤器 以下为常用过滤器

使用:

不传参

{{ var|过滤器名称 }}

传参

{{ var|过滤器名称(参数…) }}

(1) 过滤器
  1. abs 返回一个数值的绝对值

    {{ num|abs }}
    
  2. default 默认值 当变量不存在则执行默认值 如果想bool的假也执行 需要以下实例进行改变

    <p>{{ num|default('default') }}</p>
    <p>{{ xxx|default('default') }}</p>
    
    {{ bool|default('default',boolean=True) }}
    
  3. first 返回序列的第一个元素

  4. last 返回序列的最后一个元素

  5. format 格式化字符串

    {{ '我叫%s 我今年%d岁了 我的存款为 %.2f元'|format('lucky',18,123456) }}
    
  6. length 返回一个序列或者字典的长度

  7. join将一个序列拼接成字符串

    {{ List|join('-') }}
    
  8. int 将值转换为int类型

  9. float 转换为浮点型

  10. string 转换为字符串

  11. list 转换为列表

  12. lower 转换为小写

  13. upper 转换为大写

  14. replace 替换

  15. striptags 删除字符串中的所有HTML标签

  16. safe 默认为了安全考虑 是不会解析html代码的 可以使用safe进行解析输出

  17. trim 删除字符串俩侧的空白字符

(2) 自定义过滤器

实现的功能:当内容超出给定的长度以后 显示省略号

方式一

通过flask应用对象的add_templater_filter方法

视图函数

# 超出固定长度 显示省略号
def show_ellipsis(Str,length=5):
    if len(Str)>length:
        Str = Str[0:length]+'...'
    return Str

app.add_template_filter(show_ellipsis)

方式二

通过装饰器来实现自定义过滤器

# 使用过滤器实现
@app.template_filter()
def show_ellipsis(Str,length=5):
    if len(Str)>length:
        Str = Str[0:length]+'...'
    return Str
模板中使用
<h4>自定义过滤器的测试</h4>
<p>{{ name|show_ellipsis }}</p>
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值