PythonFlask教程展示了如何使用PythonFlask模块创建Python网络应用程序。
烧瓶
Flask是Python微型网络框架。它只包含一个核心库。大部分功能都可以作为扩展使用,包括验证、表单处理、对象关系映射器或身份验证。Flask基于WerkzeugWSGI工具包和Jinja2模板引擎。
Web服务器网关接口(WSGI)是Web服务器将请求转发到使用Python编程语言编写的Web应用程序或框架的简单调用约定。
烧瓶Jinja2
Jinja2是一个Flask模板引擎。模板引擎或模板处理器是一个库,旨在将模板与数据模型相结合以生成文档。模板引擎通常用于生成大量电子邮件、源代码预处理或生成动态HTML页面。
通过Jinja教程了解有关Jinja2的更多信息。
网址
统一资源定位器(URL)是对网络资源的引用,指定其在计算机网络上的位置以及检索它的机制。网络资源是可以通过网络获取的任何数据,例如HTML文档、PDF文件、PNG图像、JSON数据或纯文本。
通用URL具有以下形式:
scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
[]括号之间的部分是可选的。
烧瓶安装
$ pip3 install -U Flask
我们使用pip3工具来安装Flask。-U或--update将模块更新到最新版本。
设置虚拟环境
更复杂的应用程序在开发过程中使用虚拟环境。
$ python3 -m venv venv . venv/bin/activate
这些命令在Linux上创建了一个新的虚拟环境。
> py -3 -m venv venv > venv\Scripts\activate
这些命令在Windows上创建一个新的虚拟环境。
运行Flask应用程序
运行Flask应用程序的推荐方法是借助环境变量。
$ export FLASK_APP=hello.py $ flask run
我们将FLASK_APP设置为主应用程序文件的名称。在Windows上,使用set命令而不是export。
$ export FLASK_ENV=development
为了在开发模式下运行Flask应用程序,我们还设置了FLASK_EVN变量。
Flask简单示例
在下面的示例中,我们创建了一个简单的Flask应用程序。
$ mkdir hello $ cd hello
我们为应用程序创建一个目录。
#!/usr/bin/python
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello there!'
在一个目录中,我们创建一个Python文件hello.py。
from flask import Flask
我们导入Flask对象。它实现了一个WSGI应用程序并作为中心对象。
@app.route('/')
def hello():
return 'Hello there!'
使用@app.route装饰器,我们定义了一条路线。路由是URL和Web应用程序功能之间的映射。在我们的例子中,我们返回一条简单的文本消息。
$ flask run * Serving Flask app "hello.py" * Environment: production WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Debug mode: off * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
我们设置了FLASK_APP环境变量并使用flaskrun命令启动应用程序。默认的Flask端口是5000。
$ curl localhost:5000 Hello there!
我们使用curl命令创建一个请求。
Flask查询参数
查询字符串是URL的一部分,用于为资源请求添加一些条件。它通常是一系列键/值对。它遵循路径并以?字符开头。
#!/usr/bin/python
from flask import Flask, request
app = Flask(__name__)
@app.route('/')
def index():
return 'Home page'
@app.route('/greet', methods=['GET'])
def greet():
name = request.args.get('name', 'Guest')
msg = f'Hello {name}'
return msg, 200, {'Content-Type': 'text/plain; charset=utf-8'}
应用程序创建消息并将其发送到客户端。它使用来自name查询参数的值。
from flask import Flask, request
我们导入Flask和request对象。
@app.route('/greet', methods=['GET'])
def greet():
...
greet函数映射到/greet路径和GET类型请求。
name = request.args.get('name', 'Guest')
我们使用get方法从request对象获取查询参数。如果参数不存在,则返回默认值'Guest'。
msg = f'Hello {name}'
我们将name查询参数的值包含到消息中。
return msg, 200, {'Content-Type': 'text/plain; charset=utf-8'}
我们将消息、状态码和响应内容类型返回给客户端。
$ export FLASK_APP=app.py $ flask run
我们运行应用程序。
$ curl -i localhost:5000/greet?name=Lucia HTTP/1.0 200 OK Content-Type: text/plain; charset=utf-8 Content-Length: 11 Server: Werkzeug/0.16.0 Python/3.8.0 Date: Thu, 16 Jan 2020 15:50:58 GMT Hello Lucia
我们向应用程序创建一个GET请求。使用-i选项,我们还包括响应标头。
$ curl localhost:5000/greet Hello Guest
当没有设置查询参数时,使用默认值。
烧瓶路径参数
值可以通过查询参数或路径参数发送到网络应用程序。路径参数在尖括号之间指定:。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Home page'
@app.route("/greet/<name>/")
def greet(name):
msg = f'Hello {name}'
return msg, 200, {'Content-Type': 'text/plain; charset=utf-8'}
应用程序向用户返回问候语,其名称被指定为路径参数。
@app.route("/greet/<name>/")
def greet(name):
路径参数在这里定义:。然后将参数传递给name变量。
$ curl localhost:5000/greet/Robert/ Hello Robert
烧瓶make_response
使用make_response辅助函数,我们可以创建对客户端的响应,包括必要的标头。
#!/usr/bin/python
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/')
def hello():
return 'Home page'
@app.route('/users/<name>', methods=['POST'])
def create_user(name):
msg = f'user {name} created'
return make_response(msg, 201)
@app.route('/users/<name>', methods=['GET'])
def get_user(name):
msg = f'Hello {name}'
return make_response(msg, 200)
该应用程序由一个文件组成:app.py。它包含三个方法。
@app.route('/')
def hello():
return 'Home page'
对于主页,我们返回一条简单的文本消息。
@app.route('/users/<name>', methods=['POST'])
def create_user(name):
msg = f'user {name} created'
return make_response(msg, 201)
create_user方法映射到/users/POST请求路径。是一个路径变量,其值被传递给name变量。make_response使用正文和201状态代码创建响应。
@app.route('/users/<name>', methods=['GET'])
def get_user(name):
msg = f'Hello {name}'
return make_response(msg, 200)
get_user映射到相同的路径,但方法不同:GET。这次响应包含200状态码。
$ export FLASK_APP=app.py $ flask run
我们运行应用程序。
$ curl -i localhost:5000/users/Peter/ HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 11 Server: Werkzeug/0.16.0 Python/3.8.0 Date: Thu, 16 Jan 2020 15:31:37 GMT Hello Peter
我们向应用程序创建一个GET请求。
$ curl -X POST localhost:5000/users/Peter/ user Peter created
创建了一个POST请求。
烧瓶发送文件
send_file方法将文件的内容发送到客户端。
#!/usr/bin/python
from flask import Flask, send_file
app = Flask(__name__)
@app.route('/image')
def get_image():
filename = 'sid.png'
return send_file(filename, mimetype='image/png')
该示例向客户端发送图像。
return send_file(filename, mimetype='image/png')
我们指定文件名和内容类型。
烧瓶JSON
JSON是一种轻量级数据交换格式。它易于人类阅读和机器解析和生成。Web应用程序经常使用和生成JSON数据。
当向客户端返回Python字典时,Flask会自动将其转换为JSON。可以使用jsonify函数将其他对象转换为JSON。
from flask import Flask, jsonify, render_template
import random
app = Flask(__name__)
movies = {1: 'Toy story', 2: 'The Raid', 3: 'Hero',
4: 'Ip Man', 5: 'Kung Fu Panda'}
@app.route('/movies')
def get_movies():
return movies
@app.route('/rmovie')
def random_movie():
movie = random.choice(list(movies.items()))
return jsonify(movie)
在示例中,我们有两个函数。一个返回字典,另一个返回字典中的随机对。
@app.route('/movies')
def get_movies():
return movies
Flask自动将movies字典转换为JSON。
@app.route('/rmovie')
def random_movie():
movie = random.choice(list(movies.items()))
return jsonify(movie)
这个函数从字典中随机返回一部电影;它是一个Python元组。然后使用jsonify函数将元组转换为JSON。
$ curl localhost:5000/movies
{"1":"Toy story","2":"The Raid","3":"Hero","4":"Ip Man","5":"Kung Fu Panda"}
这里我们将所有电影作为JSON数据获取。
$ curl localhost:5000/rmovie [2,"The Raid"]
这里我们得到一部随机电影。
烧瓶渲染模板
render_template函数从具有给定上下文的模板文件夹中呈现模板。上下文是模板上下文中应该可用的变量。存放模板文件的目录默认名称为templates。
app.py
templates
index.html
这些是项目目录的内容。
#!/usr/bin/python
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/greet/<name>/')
def greet(name):
msg = f'Hello {name}'
return render_template('index.html', name=name)
在示例中,我们从路径参数中读取一个值并将其发送到要处理的index.html模板文件。
return render_template('index.html', name=name)
render_template的第一个参数是模板文件名,第二个是上下文变量。name局部变量将在name下的模板中可用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Greeting</title>
</head>
<body>
<p>
Hello {{ name }}
</p>
</body>
</html>
这是index.html模板文件。模板由静态数据和动态数据组成。
<p>
Hello {{ name }}
</p>
使用{{}}语法,我们输出传递给模板的name变量的值。
$ curl localhost:5000/greet/Peter/
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Greeting</title>
</head>
<body>
<p>
Hello Peter
</p>
</body>
</html>
Flask提供静态文件
静态文件是不会改变的文件。它们包括CSS文件、JavaScript文件和图像;还有不包含模板指令的HTML文件。Flask有一个默认的static静态文件目录。
app.py
static
about.html
sid.jpg
templates
index.html
这是项目结构。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/about')
def about():
return app.send_static_file('about.html')
我们在应用程序中有两条路线。首页呈现一个模板,模板引用一张图片。关于页面返回一个带有send_static_file函数的静态HTML文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>About</title>
</head>
<body>
<p>
About page
</p>
</body>
</html>
about.html页面是一个简单的静态HTML文件。没有模板指令。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home page</title>
</head>
<body>
<img src="/static/sid.jpg" alt="Sid">
<img src="{{ url_for('static', filename='sid.jpg') }}" alt="Sid">
</body>
</html>
在index.html模板文件中,我们引用了一个静态资源:一个图片文件。
<img src="/static/sid.jpg" alt="Sid">
<img src="{{ url_for('static', filename='sid.jpg') }}" alt="Sid">
我们将JPEG图像包含到文件中。推荐使用url_for函数,因为硬编码的URL更难维护。
Flask自定义404页面
HTTP404、404NotFound、404、PageNotFound错误消息是网络通信中使用的超文本传输协议(HTTP)标准响应代码。它表示浏览器能够与给定服务器通信,但服务器找不到所请求的内容。
Flask有一个内置的abort函数,它向客户端发送错误信息。我们可以使用errorhandler自定义错误页面。它是一个装饰器,用于通过代码或异常类注册一个函数来处理错误。
#!/usr/bin/python
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello():
return 'Home page'
@app.route('/about')
def about():
return 'About page'
@app.errorhandler(404)
def not_found_error(error):
return render_template('404.html'), 404
在示例中,我们为404notfound错误注册了一个错误处理函数。它呈现404.html模板文件。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 error</title>
</head>
<body>
<p>
404 - page not found
</p>
</body>
</html>
这是向用户显示的错误页面。
FlaskSQLite示例
在下面的示例中,我们从SQLite数据库发送数据。我们使用SQLAlchemy。
app.py data cities.sql test.db
这是项目结构。
BEGIN TRANSACTION;
DROP TABLE IF EXISTS cities;
CREATE TABLE cities(id INTEGER PRIMARY KEY, name TEXT, population INTEGER);
INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);
COMMIT;
我们使用这些数据。
$ sqlite3 test.db SQLite version 3.27.2 2019-02-25 16:06:06 Enter ".help" for usage hints. sqlite> .read cities.sql sqlite> select * from cities; 1|Bratislava|432000 2|Budapest|1759000 3|Prague|1280000 4|Warsaw|1748000 5|Los Angeles|3971000 6|New York|8550000 7|Edinburgh|464000 8|Berlin|3671000
我们将数据加载到test.db数据库中。
#!/usr/bin/python
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data/test.db'
db = SQLAlchemy(app)
class City(db.Model):
__tablename__ = 'cities'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
population = db.Column(db.Integer)
def serialize(self):
return {
'id': self.id,
'name': self.name,
'population': self.population,
}
@app.route('/cities')
def all():
cities = City.query.all()
return jsonify(cities=[city.serialize() for city in cities])
应用程序将cities表中的所有行作为JSON数据发送到客户端。
from flask_sqlalchemy import SQLAlchemy
要处理数据,我们使用flask_sqlalchemy模块。
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
因此,我们不使用flask_sqlalchemy事件系统;我们使用SQLALCHEMY_TRACK_MODIFICATIONS配置选项将其关闭。
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data/test.db'
使用SQLALCHEMY_DATABASE_URI,我们指定数据库的路径。
db = SQLAlchemy(app)
SQLAlchemy对象被创建;它用于处理数据库。
class City(db.Model):
__tablename__ = 'cities'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255))
population = db.Column(db.Integer)
def serialize(self):
return {
'id': self.id,
'name': self.name,
'population': self.population,
}
这是City实体。我们定义表名并将属性映射到数据库列。serialize方法有助于将Python类转换为JSON对象。
@app.route('/cities')
def all():
cities = City.query.all()
return jsonify(cities=[city.serialize() for city in cities])
对于/cities路由,我们从数据库中获取所有行并将它们作为JSON数据发送到客户端。
$ export FLASK_APP=app.py
$ curl localhost:5000/cities
{"cities":[{"id":1,"name":"Bratislava","population":432000},
{"id":2,"name":"Budapest","population":1759000},
{"id":3,"name":"Prague","population":1280000},
{"id":4,"name":"Warsaw","population":1748000},
{"id":5,"name":"Los Angeles","population":3971000},
{"id":6,"name":"New York","population":8550000},
{"id":7,"name":"Edinburgh","population":464000},
{"id":8,"name":"Berlin","population":3671000}]}
在本教程中,我们介绍了用于开发Web应用程序的PythonFlask模块。
列出所有Python教程。
