Flask之Jinja2模板
Jinja2模板
Fkask中的页面渲染是通过jinjia2模块实现的,依赖于render_template函数
默认在template文件路径下
模板传参
(1)如果只有一个或者少量参数,直接在render_template函数中添加关键字参数就可以了。
使用格式:
return render_template('模板文件',key=value)
(2)如果有多个参数的时候,那么可以先把所有的参数放在字典中,然后在render_template中, 使用两个星号,把字典转换成关键参数传递进去,这样的代码更方便管理和使用。
context = {
'username' : '站长',
'age' : '18',
'gender' : '男'
}
# 定义一个字典,双星号把字典转换成关键参数传递进去
return render_template('index.html' , **context)
常见语法
模版讲解:
- {{ … }}:装载一个变量,模板渲染的时候,会使用传进来的同名参数这个变量代表的值替换掉。
- {% … %}:装载一个控制语句。
- {# … #}:装载一个注释,模板渲染的时候会忽视这中间的值。
常见语法:
获取变量:
{{变量}}
分支语句:
{% if 条件A %}
语句1
{% elif 条件B %}
语句2
{%endif%}
执行流程:
那个条件为True,执行哪个语句
顺序判断
循环语句:
{% for 变量 in 容器 %}
{%endfor%}
Jinja2中for循环内置常量
- loop.index 当前迭代的索引(从1开始)
- loop.index0 当前迭代的索引(从0开始)
- loop.first 是否是第一次迭代,返回True/False
- loop.last 是否是最后一次迭代,返回True/False
- loop.length 序列的长度
具体使用
html文件内容:用了条件判断和循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>{{ title }}</title>
{% else %}
<title>这是默认标题</title>
{% endif %}
</head>
<body>
<h1>{{ user.name }}</h1>
{% for news in news_list %}
<p>{{ news.author }} say:</p><p>{{ news.article }}</p>
{% endfor %}
{# 字典遍历 #}
{% for k,v in user.items() %}
<p>{{ k }}:{{ v }}</p>
{% endfor %}
</body>
</html>
视图函数:
@app.route('/index')
def index():
user = {'name': 'paul', 'age': 18}
news_list = [
{
'author': 'xiaoming',
'article': '这是小明发的新闻内容'
},
{
'author': 'xiaohong',
'article': 'news by xiaohong'
},
{
'author': 'wang',
'article': 'wang put news'
}
]
return render_template('index.html', user=user, news_list=news_list, title='jinja')
这样写即可展示数据。
运算符
- +号运算符:可以完成数字相加,字符串相加,列表相加。但是并不推荐使用+运算符来操作字符串,字符串相加应该使用~运算符。
- -号运算符:只能针对两个数字相减。
- /号运算符:对两个数进行相除。
- %号运算符:取余运算。
- *号运算符:乘号运算符,并且可以对字符进行相乘。
- **号运算符:次幂运算符,比如2**3=8。
- in操作符:跟python中的in一样使用,比如{{1 in [1,2,3]}}返回true。
- ~号运算符:拼接多个字符串,比如{{“Hello” ~ “World”}}将返回HelloWorld。
Jiaja2模版最重要的部分——宏
- 宏相当于一个搭建好的页面一部分,可以被引入,可以往宏传递参数。可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量,在使用宏时传递参数,从而将宏渲染成为页面的一部分。
比如:定义一个input标签宏
{% macro input(name='', value='', type='text') %}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}">
{% endmacro %}
在其它地方使用这个宏快速创建出符合要求的input标签:
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
页面文件中导入宏——import
在开发中,会将一些常用的宏单独放在一个文件中,在需要使用的时候,再从这个文件中进行导入。
import语句的用法跟python中的import类似,可以直接import…as…,也可以from…import…或者from…import…as…。
{% import 'forms.html' as forms %} //导入宏文件
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd> //使用宏
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
导入模板并不会把当前上下文中的变量添加到被导入的模板中,我们可以在导入的时候使用with context 把上下文传进去:
- {% from ‘_helpers.html’ import my_macro with context %}
宏文件中引用其它宏——include
include语句可以把一个模板引入到另外一个模板中,类似于把一个模板的代码copy到另外一个模板的指定位置。
{% include 'header.html' %}
Body
{% include 'footer.html' %}
ignore missing表示有就加载这个界面,没有就忽略
{% include 'tem66.html' ignore missing %}
模板的继承
Jinja2 中模板继承的特点允许我们把所有模板公共的部分移除出页面的布局,接着把它们放在一个基础模板中,所有使用它的模板可以导入该基础模板。
所以让我们定义一个基础模板,该模板包含导航栏以及上面谈论的标题(文件 app/templates/base.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
{% if title %}
<title>{{ title }}</title>
{% else %}
<title>这是默认标题</title>
{% endif %}
</head>
<body>
<div>MyBlog: <a href="/index">Home</a> </div>
<hr>
{% block content %}{% endblock %}
</body>
</html>
在这个模板中,我们使用 block 控制语句来定义派生模板可以插入的地方。块被赋予唯一的名字。
接着现在剩下的就是修改我们的 article.html 模板继承自 base.html (文件 app/templates/article.html):
{% extends "base.html" %}
{% block content %}
<h1>Hi, {{ user.name }}!</h1>
{% for news in news_list %}
<div><p>{{ news.author }}say:<b>{{ news.article }}</b></p></div>
{% endfor %}
{% endblock %}
再写个对应的视图函数即可,这样就完成了继承
@app.route('/article')
def article():
user = {'name': 'paul'}
news_list = [
{
'author': '我是谁',
'article': '我在哪'
},
{
'author': '你是谁',
'article': '你干嘛'
},
]
return render_template('article.html', user=user, news_list=news_list, title='article')
过滤器
- 格式:{{ 容器 | 过滤器 }}
- 链式调用 {{ 容器 |过滤器1|过滤器2 }}
一些常用的过滤器:
过滤器名 | 作用 |
---|---|
sum | {{ dict_list|sum(attribute=‘age’) }},可以指定值相加 |
abs(value) | 返回一个数值的绝对值。示例:-1|abs |
default(value,default_value,boolean=false) | 如果当前变量没有值,则会使用参数中的值来代替。示例:name|default(‘xiaotuo’)——如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。 |
escape(value)或e | 转义字符,会将<、>等符号转义成HTML中的符号。显例:content|escape或content|e。 |
first(value) | 返回一个序列的第一个元素。示例:names|first |
format(value,*arags,**kwargs) | 格式化字符串。比如:{{ “%s” -"%s"|format(‘Hello?’,“Foo!”) }}将输出:Hello? - Foo! |
last(value) | 返回一个序列的最后一个元素。示例:names|last。 |
length(value) | 返回一个序列或者字典的长度。示例:names|length。 |
join(value,d=u”) | 将一个序列用d这个参数的值拼接成字符串。 |
safe(value) | 如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。 |
int(value) | 将值转换为int类型。 |
float(value) | 将值转换为float类型。 |
lower(value) | 将字符串转换为小写。 |
upper(value) | 将字符串转换为小写。 |
replace(value,old,new) | 替换将old替换为new的字符串。 |
truncate(value,length=255,killwords=False) | 截取length长度的字符串。 |
striptags(value) | 删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。 |
trim | 截取字符串前面和后面的空白字符。 |
string(value) | 将变量转换成字符串。 |
wordcount(s) | 计算一个长字符串中单词的个数。 |
自定义的过滤器
1.用装饰器来注册成过滤器,参数是在html中使用的过滤器名,不取就是函数名
@app.template_filter('rev')
def list_reverse(rev_list):
rev_list.reverse()
return rev_list
2.先定义函数,再将函数添加到过滤器@app.template_filter(函数A,‘过滤器名称’),其实作用等同于装饰器
- app.add_template_filter(list_reverse, ‘rev’)
测试器
测试器主要用来判断一个值是否满足某种类型,语法是:if…is…:
{% if variable is escaped%}
value of variable: {{ escaped }}
{% else %}
variable is not escaped
{% endif %}
Jinja2中测试器有:
callable(object) | 是否可调用。 |
---|---|
defined(object) | 是否已经被定义了。 |
escaped(object) | 是否已经被转义了。 |
upper(object) | 是否全是大写。 |
lower(object) | 是否全是小写。 |
string(object) | 是否是一个字符串。 |
sequence(object) | 是否是一个序列。 |
number(object) | 是否是一个数字。 |
odd(object) | 是否是奇数。 |
even(object) | 是否是偶数。 |
URL链接和加载静态文件
通用语法:
- url_for(‘static’,filename=‘路径’)
1.url跳转
视图函数中:
@app.route('/login/)
def login_function():
return render_template('login.html')
方法一:
<a href="/login/">点击我</a>
方法二(推荐):
<a href="{{ url_for('login_function') }}">点击我</a>
2.加载静态文件
加载css方法一:
<link rel="stylesheet" href="static/css/index.css">
方法二(推荐):
<link rel="stylesheet" href="{{ url_for('static',filename=''css/index.css) }}">
加载图片方法(推荐):
<img src="{{ url_for('static',filename='images/logo.png') }}"
加载Js文件方法(推荐):
<script src="{{ url_for('static',filename='js/index.js') }}">