【Python Web开发】Flask框架使用
Web开发框架有哪些
Java的web开发框架有Spring Boot等,而Python的web开发框架则有Django、Flask等。
Django
这是一个高级的Python Web框架,以其强大的功能和简洁的接口而闻名。它鼓励快速开发和干净的设计,非常适合大型项目。Django采用MTV(Model、Template、View)模型组织资源,功能丰富,模板扩展选择多,但可能包含一些轻量级应用不需要的功能模块。
Flask
这是一个轻量级的Python Web框架,适合小型项目和快速原型开发。Flask的核心功能简单,但扩展性极强,可以通过插件和扩展来增加更多功能。它非常适合低流量或小型工程,但可能需要安装多种插件来支持大型工程。
Flask安装
pip install Flask
pip show flask
查看安装信息
Flask框架创建项目
Pycharm→File→New Project
- 选择Flask
- 输入项目路径+项目名
- 选择解释器
运行项目
Flask基础使用
Flask框架目录结构
static
和templates
目录是默认配置。
static
用来存放静态资源,例如图片、js、css文件等。
templates
存放模板文件。
Flask配置
Flask默认使用static目录存放静态资源,templates目录存放模板,这是可以通过设置参数更改的
app = Flask("my-app", static_folder="path1", template_folder="path2") # "my-app"为该应用程序对象指定名称和根路径。
获取所有的url参数
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def hello_world():
return request.args.__str__()
if __name__ == '__main__':
app.run(port=5000, debug=True)
http://127.0.0.1:5000/?name=Flask&time&p=1&p=2
获取某个指定的参数
@app.route("/parm")
def get_parm():
return request.args.get("name")
http://127.0.0.1:5000/parm?name=张三&age=18
参数获取None问题处理
request.args.get('info')返回Python内置的None,而Flask不允许返回None。
@app.route('/')
def hello_world():
r = request.args.get('info')
if r==None:
# do something
return ''
return r
参数获取不到,设置默认值
request.args.get("name", "未获取到name参数,请检查")
参数多值处理
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def hello_world():
r = request.args.getlist('p') # 返回一个list
return str(r)
if __name__ == '__main__':
app.run(port=5000, debug=True)
获取POST方法传送的数据
from flask import Flask, request
app = Flask(__name__)
@app.route("/register", methods=["POST"])
def register():
print(request.headers) # 获取请求头
print(request.stream.read()) # 获取请求数据
return "post"
if __name__ == '__main__':
app.run(port=5000, debug=True)
解析post请求的数据
request.form
会自动解析数据。
@app.route("/register", methods=["POST"])
def register():
print(request.headers) # 获取请求头
# print(request.stream.read()) # 获取请求数据(不能和request.form一起使用,否则下面的form取不到数据)
print(request.form)
print(request.form['password']) # 键方式获取
print(request.form.get('password'))
print(request.form.get('name'))
print(request.form.getlist('name')) # 返回列表
print(request.form.get('nickname', default='去不到,默认数据'))
return "post"
请求接口
import requests
data = {"name1": "letian",
"name": "张三",
"password": "123"
}
r = requests.post("http://127.0.0.1:5000/register", data)
print(r.text)
处理JSON格式的请求数据
如果POST的数据是JSON格式,request.json
会自动将json数据转换成Python类型(字典或者列表)。
@app.route("/json", methods=["POST"])
def post_json():
print(request.headers)
print(type(request.json))
print(request.json) # 获取json请求数据
result = request.json["a"] + request.json["b"]
return str(result)
请求接口
import requests
json = {"a": 1, "b": 2}
r = requests.post("http://127.0.0.1:5000/json", json=json)
print(r.text)
# 返回 3
响应json---方案一
响应JSON时,除了要把响应体改成JSON格式
,响应头的Content-Type
也要设置为application/json
import json
from flask import Flask, request, Response
@app.route('/response_json', methods=['POST'])
def response_json():
result = {'sum': request.json['a'] + request.json['b']}
return Response(json.dumps(result), mimetype='application/json')
请求接口
json = {"a": 1, "b": 2}
r = requests.post("http://127.0.0.1:5000/response_json", json=json)
print(r.headers)
print(r.text)
响应json---方案二
使用jsonify
工具函数
@app.route('/jsonify', methods=['POST'])
def json_jsonify():
result = {'sum': request.json['a'] + request.json['b']}
return jsonify(result)
修改和新增响应头
@app.route('/response_json', methods=['POST'])
def response_json():
result = {'sum': request.json['a'] + request.json['b']}
resp = Response(json.dumps(result), mimetype='application/json') # 修改信息头
resp.headers.add('Server', 'python flask') # 添加信息头
return resp
@app.route('/jsonify', methods=['POST'])
def json_jsonify():
result = {'sum': request.json['a'] + request.json['b']}
response = jsonify({'status': 'OK', 'message': result})
response.headers['Content-Type'] = 'application/json; charset=utf-8' # 修改信息头
response.headers.add('Server', 'python flask') # 添加信息头
return response
上传文件
文件存放在,服务器端static/uploads目录下
import os
from flask import Flask, request, Response, jsonify
from werkzeug.utils import secure_filename
# 文件上传
# 文件上传目录
app.config['UPLOAD_FOLDER'] = 'static/uploads/'
# 支持的文件格式
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'} # 集合类型
# 判断文件名是否是我们支持的格式
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']
@app.route('/upload', methods=['POST'])
def upload():
upload_file = request.files['image']
if upload_file and allowed_file(upload_file.filename):
filename = secure_filename(upload_file.filename)
# 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名
upload_file.save(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
return 'info is ' + request.form.get('info', '') + '. success'
else:
return 'failed'
需要控制上产文件的大小,可以设置请求实体的大小
注意需要try:...except:...
try:
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 16MB
except Exception as e:
print(e)
获取文件内容
file_content = request.files['image'].stream.read()
URL参数化
Flask支持Restful URL的Web应用
@app.route('/user/<username>') # 请求url,参数替代
def user(username):
print(username)
print(type(username))
return 'hello ' + username
@app.route('/user/<username>/friends')
def user_friends(username):
print(username)
print(type(username))
return 'hello ' + username
转换类型
数据类型转换
@app.route('/page/<int:num>')
def page(num):
print(num)
print(type(num))
return 'hello world'
URL多参数
@app.route('/pages/<int:num1>-<int:num2>')
def pages(num1, num2):
print(num1)
print(num2)
return 'hello world'
请求:http://127.0.0.1:5000/pages/11-44
使用url_for生成链接
工具函数url_for可以让你以软编码的形式生成url,提供开发效率。
from flask import Flask, url_for
app = Flask(__name__)
@app.route('/')
def hello_world():
pass
@app.route('/user/<name>')
def user(name):
pass
@app.route('/page/<int:num>')
def page(num):
pass
# 软编码方式生成url
@app.route('/test')
def test():
print(url_for('hello_world'))
print(url_for('user', name='letian'))
print(url_for('page', num=1, q='hadoop mapreduce 10%3'))
print(url_for('static', filename='uploads/01.jpg'))
return 'Hello'
if __name__ == '__main__':
app.run(debug=True)
redirect 重定向网址
redirect函数用于重定向,实现机制很简单,就是向客户端(浏览器)发送一个重定向的HTTP报文,浏览器会去访问报文中指定的url。
@app.route('/pages/<int:num1>-<int:num2>')
def pages(num1, num2):
print(num1)
print(num2)
return 'hello world'
@app.route('/test')
def test():
return redirect(url_for('pages', num1=4, num2=6, q='hadoop mapreduce 10%3'))
*浏览器会自动重定向
Jinja2 模板引擎
Jinja2模板引擎负责渲染html
模板引擎负责MVC中的V(view,视图)这一部分。
Flask默认使用Jinja2模板引擎。
Flask与模板相关的函数有:
- flask.render_template(template_name_or_list, **context) ---常用
- flask.render_template_string(source, **context) ---常用
- flask.get_template_attribute(template_name, attribute)
创建并编辑/templates/default.html
<html>
<head>
<title>
{% if page_title %}
{{ page_title }}
{% endif %}
</title>
</head>
<body>
{% block body %}{% endblock %}
</body>
</html>
可以看到,在<head>
标签中使用了if判断,如果给模板传递了page_title变量
,显示之,否则,不显示。
<body>
标签中定义了一个名为body的block
,用来被其他模板文件继承。
创建并编辑/templates/user_info.html
{% extends "default.html" %}
{% block body %}
{% for key in user_info %}
{{ key }}: {{ user_info[key] }} <br/>
{% endfor %}
{% endblock %}
变量user_info
应该是一个字典,for循环用来循环输出键值对。
render_template使用
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'hello world'
@app.route('/user2')
def user2():
user_info = {
'name': 'letian',
'email': '1234@aa.com',
'age':0,
'github': 'https://github.com/letiantian'
}
# render_template()函数的第一个参数指定模板文件,后面的参数是要传递的数据。
return render_template('user_info.html', page_title='letian\'s info', user_info=user_info)
if __name__ == '__main__':
app.run(port=5000, debug=True)
浏览器访问http://127.0.0.1:5000/user2
查看网页源码
<html>
<head>
<title>
letian's info
</title>
</head>
<body>
name: letian <br/>
email: 1234@aa.com <br/>
age: 0 <br/>
github: https://github.com/letiantian <br/>
</body>
</html>
进群交流、获取更多干货, 请关注微信公众号:

> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。