开放的编程资料库

当前位置:我爱分享网 > Python教程 > 正文

Python 使用 Flask

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

我们导入Flaskrequest对象。

@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教程。

未经允许不得转载:我爱分享网 » Python 使用 Flask

感觉很棒!可以赞赏支持我哟~

赞(0) 打赏