赞
踩
视图函数的主要作⽤是⽣成请求的响应,这是最简单的请求。实际上,视图函数有
模板其实是⼀个包含响应⽂本的⽂件,其中⽤占位符(变量)表示动态部分,告诉模板引擎其具体的
值需要从使⽤的数据中获取
使⽤真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”
Flask是使⽤ Jinja2 这个模板引擎来渲染模板
视图函数只负责业务逻辑和数据处理(业务逻辑⽅⾯),⽽模板则取到视图函数的数据结果进⾏展示(视图展示⽅⾯)代码结构清晰,耦合度低
Flask提供的 render_template 函数封装了该模板引擎
render_template 函数的第⼀个参数是模板的⽂件名,后⾯的参数都是键值对,表示模板中变量
对应的真实值。
{{}} 来表示变量名,这种 {{}} 语法叫做变量代码块
<h1>{{ post.title }}</h1>
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 }} #}
from flask import Flask, render_template app = Flask(__name__) # 模板渲染的三步操作 # 1,将模板文件放入模板文件夹中,并设置模板语言 # 2,使用render_template进行模板渲染,将要替换的内容设置为模板变量 # 3,在模板文件中使用模板变量替换内容(找到要替换内容设置为{{模板变量名}}) @app.route('/') def index(): city_name = '北京' htm_str = render_template('baidu.html',city=city_name) return htm_str if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
from flask import Flask, render_template app = Flask(__name__) class User(): type='vip' def is_login(self): return True @app.route('/') def index(): name = 'zs' dict = { 'name': 'ls', 'age': 18 } list = [1, 2, 3, 4] htm_str = render_template('render.html',name=name,dict=dict,list=list,user=User()) return htm_str if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <label>{{ name }}</label><br/> <label>{{ dict }}</label><br/> <label>{{ dict['name'] }}</label><br/> <label>{{ dict.name }}</label><br/> <label>{{ list }}</label><br/> <label>{{ list[0] }}</label><br/> <label>{{ user.type }}</label><br/> <label>{{ user.is_login }}</label><br/> </body> </html>
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): name = 'zs' list = [1, 6, 3, 9] h1_tag='<h1>我是标题<h1>' htm_str = render_template('filtering.html',name=name,list=list,h1_tag=h1_tag) return htm_str if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <label>{{ name|lower }}</label><br/> <label>{{ list|first }}</label><br/> <label>{{ list|sum }}</label><br/> <label>{{ h1_tag|safe }}</label><br/> {#过滤块代码#} {% filter upper %} hello<br/> world {% endfilter %} </body> </html>
1.定义过滤器函数>1定义形参接收模板变量的值,>2将转换后的结果返回
2.应用添加过滤器 add_template_filter(过滤器函数引用,过滤器名称)
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): list = [1,4,9,8,2] htm_str = render_template('filtering1.html',list=list ) return htm_str # 1.定义过滤器函数>1定义形参接收模板变量的值,>2将转换后的结果返回 def li_reverse(var): return var[::-1] # 2.应用添加过滤器 add_template_filter(过滤器函数引用,过滤器名称) app.add_template_filter(li_reverse,'Li_reverse') if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<label>{{ list|Li_reverse }}</label><br/>
</body>
</html>
控制代码块主要包含两个
- 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 %}
我们可以在 Jinja2 中使⽤循环来迭代任何列表或者⽣成器函数
{% for post in posts %}
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.text | safe }}</p>
</div>
{% endfor %}
循环和if语句可以组合使⽤,以模拟 Python 循环中的 continue 功能,下⾯这个循环将只会渲染post.text不为None的那些post:
{% for post in posts if post.text %}
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.text | safe }}</p>
</div>
{% endfor %}
from flask import Flask, render_template app = Flask(__name__) @app.route('/') def index(): my_list = [ { "id": 1, "value": "我爱⼯作" }, { "id": 2, "value": "⼯作使⼈快乐" }, { "id": 3, "value": "沉迷于⼯作⽆法⾃拔" }, { "id": 4, "value": "⽇渐消瘦" }, { "id": 5, "value": "以梦为⻢,越骑越傻" } ] return render_template('if_for.html',my_list=my_list) if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for item in my_list if item.id !=5 %} {% if loop.index == 1 %} <li style="background-color: orange">{{ item.value }}</li> {% elif loop.index == 2 %} <li style="background-color: green">{{ item.value }}</li> {% elif loop.index == 3 %} <li style="background-color: red">{{ item.value }}</li> {% else %} <li style="background-color: indigo">{{ item.value }}</li> {% endif %} {% endfor %} </ul> </body> </html>
后端渲染:使用正则表达式在服务端直接对html进行替换
优点:有利于SEO(搜素引擎优化)
缺点:前后端不分离,开发效率很低
前端渲染:前端使用js对html内容进行更改,一般是发起ajax异步请求,后端以json形式返回数据,再进行拼接html
优点:前后端分离,开发效率高,局部动态刷新
缺点:不利于SEO
{% block top %} {% endblock %}
base.html
{% block top %}
顶部菜单
{% endblock top %}
{% block content %}
{% endblock content %}
{% block bottom %}
底部
{% endblock bottom %}
extends指令声明这个模板继承⾃哪
{% extends 'base.html' %}
{% block content %}
需要填充的内容
{% endblock content %}
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('content.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>顶部内容</h1>
{% block content_block %}
我是父类
{% endblock %}
<h1>底部内容</h1>
</body>
</html>
{% extends 'content_base.html' %}
{% block content_block %}
<li>势如破⽵!⼈⺠币再度连闯四道关⼝ 在岸、离岸双双升破6.42</li>
<li>凛冬已⾄,还有多少银⾏⼈在假装⼲银⾏</li>
<li>⼈⺠⽇报:部分城市楼市放松限制引关注,楼市调控不会“拉抽屉”</li>
{% endblock %}
你可以在⾃⼰的模板中访问⼀些 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
这个函数会返回之前在flask中通过flask()传⼊的消息的列表,flash函数的作⽤很简单,可以把由Python
字符串表示的消息加⼊⼀个消息队列中,再使⽤get_flashed_message()函数取出它们并消费掉:
{%for message in get_flashed_messages()%}
{{message}}
{%endfor%}
from flask import Flask, session, g, render_template, flash app = Flask(__name__) app.secret_key = 'test' @app.route('/') def index(): session['name']='ls' g.age=18 flash('登陆开始') flash('登陆结束') return render_template('demo5.html') @app.route('/home') def home(): flash('回家') return 'home' if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <label>{{ request.url }}</label><br/> <label>{{ session.name }}</label><br/> <label>{{ g.age }}</label><br/> <label>{{ url_for('index') }}</label><br/> {% for message in get_flashed_messages() %} <script>alert("{{ message }}")</script> {% endfor %} </body> </html>
CSRF 全拼为 Cross Site Request Forgery ,译为跨站请求伪造。
CSRF 指攻击者盗⽤了你的身份,以你的名义发送恶意请求。
包括:以你名义发送邮件,发消息,盗取你的账号,甚⾄于购买商品,虚拟货币转账…
造成的问题:个⼈隐私泄露以及财产安全。
步骤
import base64 import os from flask import Flask, request, render_template, url_for, redirect from flask_wtf import CSRFProtect app = Flask(__name__) # 设置随机密钥 s_key = base64.b64encode(os.urandom(48)).decode() app.secret_key = s_key # 设置csrf防护 CSRFProtect(app) @app.route('/',methods=['GET','POST']) def index(): if request.method == 'GET': return render_template('login.html') username = request.form.get('username') password = request.form.get('password') print(username,password) if username == 'ww' and password == '123': return redirect(url_for('transfer')) else: return '用户名或密码错误' @app.route('/transfer',methods=['GET','POST']) def transfer(): if request.method == 'GET': return render_template('demo2.html') to_account = request.form.get('to_account') money = request.form.get('money') return '成功转了%s给%s' % (money,to_account) if __name__ == '__main__': app.run(host='0.0.0.0', port=8080, debug=True)
<body>
<h1>欢迎来到A网站</h1>
<form action="" method="post">
<div>
<label>用户名:</label>
<input type="text" name="username" placeholder="请输入用户名">
<label>密码:</label>
<input type="password" name="password" placeholder="请输入密码">
</div>
<input type="submit" value="登陆"><br/>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
</form>
</body>
</html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎来到A网站</h1> <form action="" method="post"> <div> <label>对方账户名:</label> <input type="text" name="to_account" placeholder="请输入对方账户"> <label>金额:</label> <input type="text" name="money" placeholder="请输入金额"> </div> <input type="submit" value="转帐"><br/> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"> </form> </body> </html>
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('demo3.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>欢迎来到B网站</h1> <form action="http://127.0.0.1:8080/transfer" method="post"> <input type="hidden" name="to_account" value="haha"> <input type="hidden" name="money" value="8888888"> <input type="submit" value="领取优惠卷"> </form> </body> </html>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。