前言

这一切开始于2010年4月1日,Armin Ronacher在网上发布了一篇关于“下一代Python微框架”的介绍文章,文章里称这个Denied框架不依赖Python标准库,只需要复制一份deny.py放到你的项目文件夹就可以开始编程。伴随着一本正经的介绍、名人推荐语、示例代码和演示视频,这个“虚假”的项目让不少人都信以为真。5天后,Flask(http://flask.pocoo.org/)就从这么一个愚人节玩笑诞生了。。


1. 初识Flask

Flask是使用Python编写的Web微框架。Web框架可以让我们不用关心底层的请求响应处理,更方便高效地编写Web程序。因为Flask核心简单且易于扩展,所以被称作微框架(micro framework)。Flask有两个主要依赖,一个是WSGI(Web Server Gateway Interface,Web服务器网关接口)工具集——Werkzeug([http://werkzeug.pocoo.org/(http://werkzeug.pocoo.org/)),另一个是Jinja2模板引擎http://jinja.pocoo.org/。Flask只保留了Web开发的核心功能,其他的功能都由外部扩展来实现,比如数据库集成、表单认证、文件上传等。如果没有合适的扩展,你甚至可以自己动手开发。Flask不会替你做决定,也不会限制你的选择。总之,Flask可以变成任何你想要的东西,一切都由你做主

1.1、搭建开发环境

现在我们开始正式的搭建开发环境。

1.1.1 pipenv工作流

Pipenv是基于pip的Python包管理工具,它和pip的用法非常相似,可以看作pip的加强版,它的出现解决了旧的pip+virtualenv+requirements.txt的工作方式的弊端。具体来说,它是pip、Pipfile和Virtualenv的结合体,它让包安装、包依赖管理和虚拟环境管理更加方便,使用它可以实现高效的Python项目开发工作流。

sudo pip install pipenv   # 全局安装
pip install --user pipenv # 用户安装

具体可参考https://docs.pipenv.org/install/ #installing-pipenv

1.1.2 创建虚拟环境

在Python中,虚拟环境(virtual enviroment)就是隔离的Python解释器环境。通过创建虚拟环境,你可以拥有一个独立的Python解释器环境
可以通过--three--two选项来声明虚拟环境中使用的Python版本(分别对应Python3和Python2),或是使用--python选项指定具体的版本号。同时要确保对应版本的Python已经安装在电脑中

为当前项目创建一个文件夹,其中包含隔离的Python解释器环境,并且安装pip、wheel、setuptools等基本的包。

$ pipenv install
Creating a virtualenv for this project…
...
Virtualenv location: /path/to/virtualenv/helloflask-5Pa0ZfZw
...

默认情况下,Pipenv会统一管理所有虚拟环境。在Windows系统中,虚拟环境文件夹会在C:\Users\Administrator\.virtualenvs\目录下创建,而Linux或macOS会在~/.local/share/virtualenvs/目录下创建。如果你想在项目目录内创建虚拟环境文件夹,可以设置环境变量PIPENV_VENV_IN_PROJECT,这时名为.venv的虚拟环境文件夹将在项目根目录被创建。虚拟环境文件夹的目录名称的形式为“当前项目目录名+一串随机字符”,比如helloflask-5Pa0ZfZw

  • 显式激活虚拟环境运行
$ pipenv shell
Loading .env environment variables…
Launching subshell in virtual environment. Type 'exit' to return.
(helloflask-5Pa0ZfZw) $
  • 无需激活环境运行
$ pipenv run python hello.py

1.1.3 管理环境依赖

requirements.txt需要手动维护,在使用上不够灵活。Pipfile的出现就是为了替代难于管理的requirements.txt

在创建虚拟环境时,如果项目根目录下没有Pipfile文件,pipenvinstall命令还会在项目文件夹根目录下创建PipfilePipfile.lock文件,前者用来记录项目依赖包列表,而后者记录了固定版本的详细依赖包列表。当我们使用Pipenv安装/删除/更新依赖包时,Pipfile以及Pipfile.lock会自动更新。
安装flask:

$ pipenv install flask
Installing flask...
...
Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask

备注:

可以使用pipenv graph命令查看当前环境下的依赖情况,或是在
虚拟环境中使用pip list命令查看依赖列表。
**常用命令:**
pipenv --where    # 找到项目
pipenv --venv     # 找到virtualenv
pipenv --py       # 找到Python解释器
pipenv shell      # 激活虚拟环境
pipenv graph      # 查看当前安装的库和依赖
pipenv uninstall --all      # 卸载全部包

高级用法

pipenv install -r requirements.txt  # 将requirments.txt转换为pipfile
pipenv install -r dev-requirements.txt --dev #requirent-dev.txt加入pipfile

#在其他环境建立环境
pipenv install --ignore-pipfile   # 生成生产环境, 只需要把代码和Pipfile.lock放到生产环境
pipenv install --dev              # 生成开发环境,将代码和Pipfile复制过去

1.1.4 安装Flask

$ pipenv install flask
Installing flask...
...
Successfully installed Jinja2-2.10 MarkupSafe-1.0 Werkzeug-0.14.1 click-6.7 flask-1.0.2

$ pipenv update flask   # 更新flask

1.2 Hello,Flask!

# -*- coding: utf-8 -*-

import click
from flask import Flask

app = Flask(__name__)


# the minimal Flask application
@app.route('/')
def index():
    return '<h1>Hello, World!</h1>'


# bind multiple URL for one view function
@app.route('/hi')
@app.route('/hello')
def say_hello():
    return '<h1>Hello, Flask!</h1>'


# dynamic route, URL variable default
@app.route('/greet', defaults={'name': 'Programmer'})
@app.route('/greet/<name>')
def greet(name):
    return '<h1>Hello, %s!</h1>' % name


# custom flask cli command
@app.cli.command()
def hello():
    """Just say hello."""
    click.echo('Hello, Human!')

1.3 启动开发服务器

Flask通过依赖包Click内置了一个CLI(Command Line Interface,命令行交互界面)系统。当我们安装Flask后,会自动添加一个flask命令脚本,我们可以通过flask命令执行内置命令、扩展提供的命令或是我们自己定义的命令。其中,flask run命令用来启动内置的开发服务器:

$ flask run          # 已激活虚拟环境
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

备注:

$ pipenv run flask run   # 未激活虚拟环境
$ python-m flask run     # 遇到command not found 错误
$ flask run --host=192.168.1.1 --port=8000 # 使服务器外部可见,并改变默认端口

Flask的自动发现程序实例机制还有第三条规则:如果安装了python-dotenv,那么在使用flask run或其他命令时会使用它自动从.flaskenv文件和.env文件中加载环境变量。

当安装了python-dotenv时,Flask在加载环境变量的优先级是:手动设置的环境变量>.env中设置的环境变量>.flaskenv设置的环境变量

为了避免频繁设置环境变量,我们可以使用python-dotenv管理项目的环境变量,首先使用Pipenv将它安装到虚拟环境:

$ pipenv install python-dotenv

Installing python-dotenv...
Adding python-dotenv to Pipfile's [packages]...
Installation Succeeded
Installing dependencies from Pipfile.lock (a835b0)...
  ================================ 0/0 - 00:00:00
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

我们在项目根目录下分别创建两个文件:.env和.flaskenv.flaskenv用来存储和Flask相关的公开环境变量,比如FLASK_APP;而.env用来存储包含敏感信息的环境变量,比如后面我们会用来配置Email服务器的账户名与密码。在.flaskenv.env文件中,环境变量使用键值对的形式定义,每行一个,以#开头的为注释,如下所示:

SOME_VAR=1
# 这是注释
FOO="BAR"
FLASK_ENV=development

备注:

Flask提供了一个FLASK_ENV环境变量用来设置环境,默认production(生产)。在开发时,我们可以将其设为development开发),这会开启所有支持开发的特性。为了方便管理,我们将把环境变量FLASK_ENV的值写入.flaskenv文件中:

1.4 Flask 扩展

扩展(extension)即使用Flask提供的API接口编写的Python库,可以为Flask程序添加各种各样的功能。以某扩展实现了Foo功能为例,这个扩展的名称将是Flask-FooFoo-Flask;程序包或模块的命名使用小写加下划线,即flask_foo(即导入时的名称);

from flask import Flask
from flask_foo import Foo

app = Flask(__name__)
foo = Foo(app)

1.5 项目配置

在一个项目中,会用到许多配置: Flask提供的配置,扩展提供的
配置,还有程序特定的配置
。和平时使用变量不同,这些配置变量都通
Flask对象的app.config属性作为统一的接口来设置和获取,它指向的
Config类实际上是字典的子类,所以可以像操作其他字典一样操作它。flask配置文档(flask.pocoo.org/docs/latest/config/)

  • 可以像在字典中添加一个键值对一样来设置一个配置:
app.config['ADMIN_NAME'] = 'Peter'
  • 使用update()方法则可以一次加载多个值:

配置的名称必须全大写,小写的变量将不会被读取。

app.config.update(
TESTING=True,
SECRET_KEY='123456'
)
  • 读取配置
value = app.config['ADMIN_NAME']

1.6 URL与端点

用Flask提供的url_for()函数获取URL,当路由中定义的URL规则被修改时,这个函数总会返回正确的URL,增强代码的易用性。

from flask import Flask, url_for

app = Flask(__name__)


@app.route('/login')
def login():
    return 'login'


@app.route('/user/<username>')
def profile(username):
    return 'hello %s' % username


with app.test_request_context():
    print(url_for('login'))                                       # 获取相对url路径
    print(url_for('profile', username='JohnDoe'))                 # 获取带参数相对url路径
    print(url_for('profile', username='JohnDoe', _external=True)) # 获取绝对路径

output:

/login
/user/JohnDoe
http://localhost/user/JohnDoe

1.7 Flask 命令

@app.cli.command()
def hello():
	click.echo('Hello, Human!')

运行:

$ flask hello
Hello, Human!

1.8 模板与静态文件

模板(template)和静态文件(static file)来生成更加丰富的网页。模板即包含程序页面的HTML文件,静态文件则是需要在HTML文件中加载的CSS和JavaScript文件,以及图片、字体文件等资源文件。默认情况下,模板文件存放在项目根目录中的templates文件夹中,静态文件存放在static文件夹下,这两个文件夹需要和包含程序实例的模块处于同一个目录下,对应的项目结构示例如下所示:

hello/
	- templates/
	- static/
	- app.py

1.9 Flask与MVC架构

MVC架构最初是用来设计桌面程序的,后来也被用于Web程序,应用了这种架构的Web框架有Django、Ruby on Rails等。在MVC架构中,程序被分为三个组件数据处理(Model)、用户界面(View)、交互逻(Controller)。如果套用MVC架构的内容,那么Flask中视图函数的名称其实并不严谨,使用控制器函数(Controller Function)似乎更合适些,虽然它也附带处理用户界面。严格来说,Flask并不是MVC架构的框架,因为它没有内置数据模型支持

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐