免费在线电影观看,日怒徽记交给谁,楚
flask内置的模板语言,它的设计思想来源于 django 的模板引擎,并扩展了其语法和一系列强大的功能。
渲染模版函数
from flask import flask, render_template @app.route('/') def index(): return render_template('')
templates
文件夹,用于存放所有的模板文件,并在目录下创建一个模板html文件
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>title</title> </head> <body> 我的模板html内容 </body> </html>
{{}} 来表示变量名,这种 {{}} 语法叫做变量代码块
视图代码:
@app.route("/") def index(): title = "网页标题" return render_template("",title=title)
模板代码
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>{{title}}</title> </head> <body> <h1>{{title}}</h1> </body> </html>
jinja2 模版中的变量代码块可以是任意 python 类型或者对象,只要它能够被 python 的 str() 方法转换为一个字符串就可以,比如,可以通过下面的方式显示一个字典或者列表中的某个元素:
{{your_dict['key']}} {{your_list[0]}}
用 {%%} 定义的控制代码块,可以实现一些语言层次的功能,比如循环或者if语句
{% if user %} {{ user }} {% else %} hello! <ul> {% for index in indexs %} <li> {{ index }} </li> {% endfor %} </ul>
使用 {# #} 进行注释,注释的内容不会在html中被渲染出来
{# {{ name }} #}
你可以在自己的模板中访问一些 flask 默认内置的函数和对象
你可以从模板中直接访问flask当前的config对象:
{{config.sqlalchemy_database_uri}} sqlite:///database.db
就是flask中代表当前请求的request对象:
{{request.url}} http://127.0.0.1
为flask的session对象
{{session.new}} true
在视图函数中设置g变量的 name 属性的值,然后在模板中直接可以取出
{{ g.name }}
url_for会根据传入的路由器函数名,返回该路由对应的url,在模板中始终使用url_for()就可以安全的修改路由绑定的url,则不比担心模板中渲染出错的链接:
{{url_for('home')}}
如果我们定义的路由url是带有参数的,则可以把它们作为关键字参数传入url_for(),flask会把他们填充进最终生成的url中:
{{ url_for('post', post_id=1)}} /post/1
主要包含两个:
- if/else if /else / endif - for / endfor
jinja2 语法中的if语句跟 python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:
{%if user.is_logged_in() %} <a href='/logout'>logout</a> {% else %} <a href='/login'>login</a> {% endif %}
过滤器可以被用在 if 语句中:
{% if comments | length > 0 %} there are {{ comments | length }} comments {% else %} there are no comments {% endif %}
{% for post in posts %} <div> <h1>{{ post.title }}</h1> <p>{{ post.text | safe }}</p> </div> {% endfor %}
{% for post in posts if post.text %} <div> <h1>{{ post.title }}</h1> <p>{{ post.text | safe }}</p> </div> {% endfor %}
变量 | 描述 |
---|---|
loop.index | 当前循环迭代的次数(从 1 开始) |
loop.index0 | 当前循环迭代的次数(从 0 开始) |
loop.revindex | 到循环结束需要迭代的次数(从 1 开始) |
loop.revindex0 | 到循环结束需要迭代的次数(从 0 开始) |
loop.first | 如果是第一次迭代,为 true 。 |
loop.last | 如果是最后一次迭代,为 true 。 |
loop.length | 序列中的项目数。 |
loop.cycle | 在一串序列间期取值的辅助函数。见下面示例程序。 |
{% for post in posts%} {{loop.index}}, {{post.title}} {% endfor %}
1, post title 2, second post
{% for post in posts%} {{loop.cycle('odd','even')}} {{post.title}} {% endfor %}
odd post title even second post
过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 python 中的某些方法,那么这就用到了过滤器。
使用方式:
{{variable | filter_name(*args)}}
{{variable | filter_name }}
在 jinja2 中,过滤器是可以支持链式调用的,示例如下:
{{ "hello world" | reverse | upper }}
<p>{{ '<em>hello</em>' | safe }}</p>
<p>{{ 'hello' | capitalize }}</p>
<p>{{ 'hello' | lower }}</p>
<p>{{ 'hello' | upper }}</p>
<p>{{ 'hello' | title }}</p>
<p>{{ 'olleh' | reverse }}</p>
<p>{{ '%s is %d' | format('name',17) }}</p>
<p>{{ '<em>hello</em>' | striptags }}</p>
<p>{{ 'hello every one' | truncate(9)}}</p>
<p>{{ [1,2,3,4,5,6] | first }}</p>
<p>{{ [1,2,3,4,5,6] | last }}</p>
<p>{{ [1,2,3,4,5,6] | length }}</p>
<p>{{ [1,2,3,4,5,6] | sum }}</p>
<p>{{ [6,2,3,1,5,4] | sort }}</p>
{% filter upper %} #一大堆文字# {% endfilter %}
过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:
重要:自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。
需求:添加列表反转的过滤器
方式一
通过调用应用程序实例的 add_template_filter 方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:
def do_listreverse(li): # 通过原列表创建一个新列表 temp_li = list(li) # 将新列表进行返转 temp_li.reverse() return temp_li app.add_template_filter(do_listreverse,'lireverse')
方式二
用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。
@app.template_filter('lireverse') def do_listreverse(li): # 通过原列表创建一个新列表 temp_li = list(li) # 将新列表进行返转 temp_li.reverse() return temp_li
<br/> my_array 原内容:{{ my_array }} <br/> my_array 反转:{{ my_array | lireverse }}
my_array 原内容:[3, 4, 2, 1, 7, 9] my_array 反转:[9, 7, 1, 2, 4, 3]
在模板中,可能会遇到以下情况:
像遇到这种情况,可以使用 jinja2 模板中的 继承 来进行实现
模板继承是为了重用模板中的公共内容。一般web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。
{% block top %} {% endblock %}
父模板代码:
base.html
{% block top %} 顶部菜单 {% endblock top %} {% block content %} {% endblock content %} {% block bottom %} 底部 {% endblock bottom %}
子模板代码:
{% extends 'base.html' %} {% block content %} 需要填充的内容 {% endblock content %}
模板继承使用时注意点:
config.py
class config(object): debug = true secret_key = "abcccddgadsag"
main.py
from flask import flask from config import config from flask import render_template app = flask(__name__,template_folder='templates') app.config.from_object(config) from flask import session @app.route("/set_session") def set_session(): session["username"] = 'request数据' return "ok" from flask import g @app.route("/") def index(): title = "网页标题" dict1 = {"id":1,"username":"xiaoming","money":20.5} love = ['睡觉','吹牛','敲代码'] g.list1 = ['睡觉','吹牛','敲代码'] g.book_list = [ {"id":1,"name":"浪潮之巅","price":88.5}, {"id":12,"name":"数学之美","price":68.5}, {"id":12,"name":"数学之美","price":68.5}, {"id":12,"name":"数学之美","price":68.5}, {"id":13,"name":"硅谷之谜","price":108.533333}, {"id":14,"name":"五年高考三年模拟","price":78.5}, ] g.title2 = '<script>alert("大标题")</script>' g.question = '如果x=10,x<y,y>z,求z的取值范围?' return render_template("",title=title,dict1=dict1,love=love) """自定义过滤器""" def rev(data): data.reverse() return data app.add_template_filter(rev,'myrev') @app.route("/filter") def myfilter(): g.list1 = ['睡觉', '吹牛', '敲代码'] return render_template("f.html") if __name__ == '__main__': app.run()
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>{{title}}</title> </head> <body> <h1>{{title}}</h1> <table border="1" width="400"> <tr> <th>id</th> <th>姓名</th> <th>存款</th> </tr> <tr> <td>{{ dict1["id"] }}</td> <td>{{ dict1["username"] }}</td> <td>{{ dict1["money"] }}</td> </tr> <tr> <td>{{ dict1.id }}</td> <td>{{ dict1.username }}</td> <td>{{ dict1.money }}</td> </tr> </table> <ul> <li>{{ love.0 }}</li> <li>{{ love.1 }}</li> <li>{{ love.2 }}</li> <li>{{ love[0] }}</li> <li>{{ love[1] }}</li> <li>{{ love[2] }}</li> {# for循环也支持多层的嵌套或者其他语句 #} {% for item in love %} <li>{{ item }}</li> {% endfor %} </ul> {# 这里是if判断,if还可以支持多个条件的判断 #} {% if dict1.money < 20 %} <p>存款太少了,需要充值</p> {% endif %} {# 特殊变量 #} {# 支持直接读取配置信息 #} <p>{{ config.secret_key }}</p> {# 支持获取请求信息 #} <p>{{ request.method }}</p> {# 支持获取session数据 #} <p>{{ session.username }}</p> {# 支持获取g变量 #} <p>{{ g.list1 }}</p> {# 支持使用url_for生成地址 #} <a href="{{ url_for("set_session") }}">跳转到sesion</a> {# for循环中还内置了循环对象loop,可以操作循环过程中的索引 #} <table border="1" width="600"> <tr> <th>序号</th> <th>id</th> <th>书名</th> <th>价格</th> </tr> {% for book in g.book_list %} {% if loop.first %} <tr style="background-color: orange;"> {% elif loop.last %} <tr style="background-color: blue;color: #fff;"> {% else %} <tr> {% endif %} <td>{{ loop.revindex }}</td> <td>{{ "%03d" % book.id }}</td> <td>{{ book.name }}</td> <td>{{ book.price }}</td> </tr> {% endfor %} </table> {# 过滤器 #} {{ dict1.username | upper | reverse }} {# 默认情况下, flask会自动针对html标签进行实体化转移,目的时为了防止xss攻击 但是,我们后端也会有一些包含样式的内容要输出页面中,此时可以使用 safe 过滤器 #} {{ g.title2 | safe }} {# 这个过滤器会直接删除html标签,也是为了防止xss攻击,但是这个过滤器慎用,在遇到数学公式的时候,会误伤. #} {{ g.title2 | striptags }} {{ g.question | striptags }} {# 字符长度截取 #} <p>{{ 'hello every one' | truncate(9)}}</p> {% filter upper %} dasdasd dsa das ds ad <p>{{ 'hello every one' | truncate(9)}}</p> asd asdas {% endfilter %} {{ "hwello" }} </body> </html>
在 flask 中, flask-wtf 扩展有一套完善的 csrf 防护体系,对于我们开发者来说,使用起来非常简单
1 设置应用程序的 secret_key,用于加密生成的 csrf_token 的值
# session加密的时候已经配置过了.如果没有在配置项中设置,则如下: app.secret_key = "#此处可以写随机字符串#"
2 导入 flask_wtf.csrf 中的 csrfprotect 类,进行初始化,并在初始化的时候关联 app
from flask.ext.wtf import csrfprotect csrfprotect(app)
3 在表单中使用 csrf 令牌:
<form method="post" action="/"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" /> </form>
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
Python 实现将numpy中的nan和inf,nan替换成对应的均值
python爬虫把url链接编码成gbk2312格式过程解析
网友评论