flask(1.0)
[toc]
一. 关于KeyError
和IndexError
KeyError
dic = {"name": "王乃卉", "age": "19", "gender": "女"}
print(dic["names"])
# 执行结果:
# KeyError: 'names'
IndexError
lst = ["a", "b", "c"]
print(lst[3])
# 执行结果:
# IndexError: list index out of range
二. Python三大主流框架对比
Django 主要特点是大而全,集成了很多组件(例如Models、Admin、Form等等), 不管你用得到用不到,反正它全都有,属于全能型框架,通常用于大型Web应用,由于内置组件足够强大所以使用Django开发可以一气呵成,优点是大而全,缺点也就暴露出来了,这么多的资源一次性全部加载,肯定会造成一部分的资源浪费;
Tornado 主要特点是原生异步非阻塞,在IO密集型应用和多任务处理上占据绝对性的优势,属于专注型框架,通常用于API后端应用,游戏服务后台,其内部实现的异步非阻塞真是稳得一批,优点是异步,缺点是干净,连个Session都不支持;
Flask 主要特点小而轻,原生组件几乎为0,三方提供的组件(请参考Django)非常全面,属于短小精悍型框架,通常应用于小型应用和快速构建应用,其强大的三方库,足以支撑一个大型的Web应用,优点是精悍简单,缺点是稳定性较差,主要因为其组件都是第三方提供,要等第三方收到更新版本通知后才能更新,否则会出现一些兼容问题;
三. flask基础
1.安装flask
pip install flask
2.用flask写出的第一个页面
from flask import Flask # 导入Flask类
app = Flask(__name__) # 实例化Flask对象
@app.route("/") # app对象中的route装饰器
def index(): # 视图函数
return "Hello Flask"
if __name__ == '__main__':
app.run() # 启动flask web服务
启动该程序, 控制台和浏览器显示如下:
3.Flask的Response"三剑客"
我们知道django中的Response有3种形式(HttpResponse
、redirect
、render
),对比django,来看一下flask中有哪些返回形式。
(1)返回HttpResponse
对象
@app.route("/")
def index():
return "Hello Flask" # 相当于django中的HttpResponse
(2)重定向redirect
from flask import redirect # 导入flask中的redirect
@app.route("/home")
def home():
return redirect("/login") # 重定向至"/login"路径
(3)返回模板页面render_template
from flask import render_template # 导入flask中的render_template
@app.route("/login")
def login():
return render_template("login.html") # 渲染模板login.html
新建一个templates
文件夹, 在该文件夹中创建login.html
文件:
4. flask之jsonify
,send_file
(1)jsonify
返回标准的json字符串
from flask import jsonify
@app.route("/jsons")
def jsons():
dic = {"name":"wnaglihong"}
return jsonify(dic)
返回json字符串,并且会在响应头中加Content-Type:application/json
,即告诉浏览器数据是json字符串,浏览器收到后会自动进行反序列化,而使用json.dumps()
则不会加此响应头。
(2)send_file
打开文件并返回文件内容(自动识别文件格式)
from flask import send_file
@app.route("/flie")
def file():
return send_file("01.mp4")
send_file
自动识别文件类型,即在返回文件内容时加一个响应头Content-Type:文件类型
。
5. flask中的request(公共变量)
每个框架中都有处理请求的机制,但是每个框架的处理方式和机制是不同的,为了了解Flask的request中都有什么,我们先来写一个基于html+flask
前后端交互的示例。
html页面代码:
<body>
<form action="/login" method="post">
用户名:<input type="text" name="username">
<br>
密码:<input type="password" name="password">
<br>
<input type="submit" value="登录">
</form>
</body>
flask代码:
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route("/login", methods=["GET", "POST"])
def login():
if request.method == "GET":
print(request.args.get("name")) # 查看url中的参数
print(request.args.to_dict()) # 获取url参数字典
return render_template("login.html")
else:
print(request.form.get("password")) # 获取form数据内容
print(list(request.form.items())) # 获取form数据内容
print(request.values) # 有大坑!!!!!!
return "OK"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=9527, debug=True)
request.method
-- 获取请求方式request.args
-- 获取url中的参数request.args.get()
request.args.to_dict()
request.form
-- 获取客户端提交来的FormData数据request.form.get()
request.form.to_dict()
request.json
-- 请求头中含有Content-Type:application/json
时, 数据会在request.json
中request.data
-- 如果提交时请求头中的Content-Type
无法被识别,将请求体中的原始数据保存,bytes类型request.files
-- 序列化文件, 存储用save()
方法,且可以通过filename
获取文件名my_file = request.files.get("my_file")
my_file.save(my_file.filename)
request.values
-- 只要是个参数都保存在其中,用于查看,不要使用to_dict()
,键重复会覆盖request.cookies
-- 存在浏览器端的字符串也会一起带过来request.headres
-- 请求头中的信息杂项: 获取各种路径
request.path
request.url
request.base_url
request.host
request.host_url
6. jinja2
(1)简介
同django的模板语法类似,flask使用的jinja2的语法,且同django的模板语法很类似,下面简单介绍一下使用方法,对比django的理解和记忆:
后端数据如下:
STUDENT = {
'id':1, 'name': 'zhangsan', 'age':15, 'gender': 'male'
}
STU_LIST = [
{'id':1, 'name': 'zhangsan', 'age':15, 'gender': 'male'},
{'id':2, 'name': 'lisi', 'age':18, 'gender': 'female'},
{'id':3, 'name': 'wangwu', 'age':25, 'gender': 'buzhidao'}
]
STU_DICT = {
1: {'name': 'zhangsan', 'age':15, 'gender': 'male'},
2: {'name': 'lisi', 'age':18, 'gender': 'female'},
3: {'name': 'wangwu', 'age':25, 'gender': 'buzhidao'}
}
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/index")
def index():
return render_template("index.html", stu=STUDENT, stu_list=STU_LIST, stu_dict=STU_DICT)
index.html
页面中jinja2渲染语法如下:
<body>
<table border="1"cellpadding="0"cellspacing="0">
<tr>
<td>{{ stu.id }}</td>
<td>{{ stu.name }}</td>
<td>{{ stu.get('age') }}</td>
<td>{{ stu['gender'] }}</td>
</tr>
</table>
<br>
<table border="1"cellpadding="0"cellspacing="0">
{% for item in stu_list %}
<tr>
<td>{{ item.name }}</td>
<td>{{ item.get('age') }}</td>
<td>
{% if item['gender']=='male' or item['gender']=='female' %}
{{ item['gender'] }}
{% else %}
male
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<br>
<table border="1"cellpadding="0"cellspacing="0">
{% for key,value in stu_dict.items() %}
<tr>
<td>{{ key }}</td>
<td>{{ value.name }}</td>
<td>{{ value.get('age') }}</td>
<td>{{ value['gender'] }}</td>
</tr>
{% endfor %}
</table>
</body>
总结: 对比django可以发现几点不同:
- 第一, jinja2语法也可以调用方法, 但调用方法要加括号;
- 第二, jinja2中字典取值除了可以使用点(
.
)语法, 还有字典的get方法和[key]取值.
(2)引用变量和执行函数都使用{{}}
{{}}
除了可以传递变量, 还可以传递函数, 如下所示:
def add(a,b):
return a+b
@app.route('/index')
def index():
return render_template('index.html', func=add)
在模板文件index.html
中直接使用{{ func(1,2) }}
便可以渲染出函数执行的结果.
(3)写逻辑代码时使用{%%}
(4)Markup
安全标签字符串
为了防止xss攻击, flask会把传递给模板文件的数据转换为文本格式, 例如:
# 视图函数app.py
@app.route("/markup")
def markup():
html = "<h1>markup_test</h1>"
return render_template("markup.html", html=html)
# 模板文件markup.html
{{ html }}
使用Markup
可以解决这个问题, Markup
安全标签字符串, 相当于django中的过滤器safe
, 使用方法如下:
# 视图函数app.py
@app.route("/new_markup")
def new_markup():
html = "<h1>markup_test</h1>"
new_html = Markup(html)
return render_template("markup.html", html=new_html)
# markup.html
{{ html }}
(5)装饰器@app.template_global()
我们虽然可以使用render_template()
等方式向模板页面中传递函数, 但是如果有许多页面都需要执行同一个函数, 就不得不向每一个页面都传递一次. 使用装饰器template_global()
则简便得多, 只需书写一次, 就可以在任何一个模板文件中都使用该函数了.
@app.template_global()
def add(a, b):
return a + b
在任何一个模板文件中都可以调用add函数: {{ add(1, 2) }}
(6)装饰器@app.template_filter()
@app.template_filter()
def fil(a, b, c):
return a + b + c
在模板文件中使用方法是 {{ 2|fil(3, 4) }}
, 与django中的过滤器用法相似: 管道符前面的数作为fil
函数的第一个参数, 管道符后面的函数fil
直接调用执行.
(7)宏指令(使用较少)
# 视图函数macro.py
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/macro")
def macro():
return render_template("macro.html")
if __name__ == '__main__':
app.run()
# 模板文件macro.html
<body>
{% macro create_input(ty, na) %}
{{ na }}: <input type="{{ ty }}" name="{{ na }}">
{% endmacro %}
{{ create_input("text", "username") }}
{{ create_input("password", "password") }}
</body>
(8)继承和导入
flask模板文件的继承和导入同django类似:
- 一个页面中导入另一个页面:
{% include "header.html" %}
- 一个页面继承另一个页面:
{% extends "base.html" %}
- 定义block块:
{% block 名字 %}
7. Flask中的session(公共变量)
from flask import Flask
app = Flask(__name__)
app.secret_key = "salt" # salt是加密字符串,可随意设置,用于序列化和反序列化session信息
我们知道cookie和session的区别是cookie存在客户端,session存在服务器端,但是flask中为了节省开销,Flask中默认Session 存放位置是客户端的Cookies中,因此在flask中用Session需要加密,也就是一定要加secret_key。
- flask中添加一个session的语法:
session["user"]="%^$&@!"
- 工作机制: 由
secret_key
+session
加密后存放在浏览器的cookie中 - 验证session机制: 当请求进入视图函数, 带上cookie, 将session从cookie序列化出来, 通过secret_ley反序列化成字典
flask(1.0)的更多相关文章
- Airflow安装异常:ERROR: flask-appbuilder 1.12.3 has requirement Flask<2,>=0.12, but you'll have flask 0.11.1 which is incompatible.
1 详细异常: ERROR: flask-appbuilder 1.12.3 has requirement Flask<2,>=0.12, but you'll have flask 0 ...
- [Python] Flask从0到1开发轻量级网页
概述 Flask采用MVT模型,即Model, Template, View Model:定义数据的存储格式,并且提供了数据库访问的API View:定义那些数据被显示,是业务逻辑处理模块 Templ ...
- [py]flask从0到1-模板/增删改查
flask知识点 1.后端渲染html到前端 render_template 2.后端获取前端数据 request.args.get 3.前端获取后端数据 模板 4.警示消息 flash {{ get ...
- flask(3.0)
目录 一.Flask - CBV 二.Flask - Session 1.安装flask-session 2.回顾flask自带的session的使用方法 3.flask-session的使用(以保存 ...
- flask(2.0)
目录 一. Flask基础(一) 1.Flask启动 2.路由 3.Response 4.Request 5.Jinja2 6.session 二.Flask基础(二) 1.路由配置 (1)metho ...
- Flask:操作SQLite3(0.1)
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2 本文介绍了第一次在Flask框架中操作SQLite3数据库的测试,参考了官网的文档Using SQLite 3 wit ...
- Flask:cookie 和 session (0.1)
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2 Cookie是什么?有什么用? 某些网站为了辨别用户身份.进行 session 跟踪而储存在用户本地终端上的数据(通常 ...
- Flask:静态文件&模板(0.1)
Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2 前面看了Flask的Quickstart文档,可是,一直没有练习里面的内容,这不,刚刚练习完毕,来写篇博文记录一下! ...
- Flask 发布 1.0 稳定版
简评:现在都开始版本大跃进了吗?对,别看别人,说的就是你 pipenv(名单太长,待补齐...) Flask 其实早就已经十分稳定了,而在第一个 commit 大概 8 年之后,版本号才最终反映出了这 ...
随机推荐
- 域知识深入学习一:Active Directory 域服务
AD DS用来组织,管理,控制网络资源 1.1 Active Directory 域服务概述 AD内的directorydatabase(目录数据库)用来存储用户账户,计算机账户,打印机与共享文件 ...
- [TJOI2019]唱、跳、rap和篮球——容斥原理+生成函数
先附一组sd图 然后放上原题链接 注意,队伍不同指的是喜好不同,不是人不同 先想到\(DP\),然后你会发现并没有什么优秀的状态设计,然后我们考虑容斥 设\(lim\)表示选的癌坤组数的上限,\(f_ ...
- java Timer和TimerTask(简单的使用)
Timer 是一个定时工具 TimerTask 是一个实现了Runnable接口抽象类,代表可以被Timer执行的任务 (1)Timer.schedule(TimerTask task,Date ti ...
- LiteOS的内核——RTOS基本的特性
在其他的rtos中,基本上也有类似的功能,ucos freertos,要是rtos的时候,务必选择自带的rtos功能,和裸机运行时有区别的
- Springboot项目关闭Httpclient的Debug日志
今天在做httpclient测试时,发现控制台打印了好多请求相关的信息,如何去掉这些不打印? (2)在配置文件包下加入logback.xml文件,文件内容如下: <?xml version=&q ...
- filter(expr|obj|ele|fn)筛选出与指定表达式匹配的元素集合。
filter(expr|obj|ele|fn) 概述 筛选出与指定表达式匹配的元素集合. 这个方法用于缩小匹配的范围.用逗号分隔多个表达式 参数 exprStringV1.0 字符串值,包含供匹配当前 ...
- jQuery系列(八):jQuery的位置信息
1.宽度和高度 (1):获取宽度 .width() 描述:为匹配的元素集合中获取第一个元素的当前计算宽度值.这个方法不接受任何参数..css(width) 和 .width()之间的区别是后者返回一个 ...
- JVM——内存结构
一.程序计数器/PC寄存器 (Program Counter Registe) 用于保存当前正在执行的程序的内存地址(下一条jvm指令的执行地址),由于Java是支持多线程执行的,所以程序执行的轨迹不 ...
- Appium进阶教程
Monkey的使用 adb shell monkey -p com.lqr.wechat -v 500 > monkey.log adb shell monkey -p com.lqr.wech ...
- 浅谈C语言和C++中“类”的区别
在C语言中,没有“类”的概念,但是可以由结构体struct构造出我们所需要的数据类型,struct可以组合不同的数据类型,可以看作是C语言中的“类”. 下面是C语言中的结构体的实例. #include ...