Flask蓝本(blueprint)
上一章我们是将所有的Flask的请求方法都写在同一个文件下,这种方式非常不便于我们的代码管理及后期的维护,此时就需要所谓的蓝本来解决这个问题了。
我们知道,Django中的app的主要作用就是将Django的项目分成一个个单独的app,然后将所有的app分配不同的处理功能,通过路由分配将它们连接成一个大的Django项目,其实Flask中的蓝本和Django中的app功能大同小异,下面我们大概的学习一下Flask的蓝本。
一 小型应用
1.1 目录结构
1.2 相应代码
account.py
from flask import Blueprint,render_template account = Blueprint('account',__name__) # 蓝本通过实例化一个Blueprint类对象创建,且必须包含两个指定参数:名称和蓝本所在的包或模块,与应用一致,多数情况下第二个参数使用__name__ # 自定义静态文件,模板文件路径,系统会优先在templates,static中寻找,没有则在指定的路径中寻找 # account = Blueprint('account',__name__,template_folder='xxx') @account.route('/login') def login(): # 视图函数的名字不能和蓝本对象的名字一致 return render_template('login.html') @account.route('/logout') def logout(): return 'Logout'
user.py
from flask import Blueprint user = Blueprint('user',__name__) @user.route('/list') def list(): return 'List' @user.route('/detail') def detail(): return 'Detail'
views/__init__.py
from flask import Flask # 导入蓝本 from .views.account import account from .views.user import user app = Flask(__name__) # 把蓝本注册到app中 app.register_blueprint(account) app.register_blueprint(user,url_prefix = '/api') # 指定前缀路径,访问路径:http://127.0.0.1:5000/api/...
manage.py
from flask_crm import app if __name__ == '__main__': app.run()
二 大型应用
2.1 目录结构
2.2 相应代码
admin/views.py
from . import admin @admin.route('/index') def index(): return 'Admin.Index'
admin/__init__.py
from flask import Blueprint admin = Blueprint( 'admin', __name__, template_folder='templates', static_folder='static' ) from . import views # 该部分视图保存在views.py中,导入该模块就能把路由与蓝本关联起来。有其他部分,也需要一起导入,比如:errors.py(自定义错误画面) # 注意:必须在__init__.py脚本的末尾导入,这是为了避免循环导入依赖,因为在app/auth/views.py中还要导入auth蓝本, # 所以除非循环引用出现在定义auth之后,否则会致使导入出错。
web/views.py
from . import web @web.route('/index') def index(): return 'Web.Index'
web/__init__.py
from flask import Blueprint web = Blueprint( 'web', __name__, template_folder='templates', static_folder='static' ) from . import views
__init__.py
from flask import Flask from .admin import admin from .web import web app = Flask(__name__) # 可以创建一个函数,def create_app():app=Flask(__name__),启动文件先创建app=create_app(),再使用app.run() app.debug = True app.register_blueprint(admin, url_prefix='/admin') app.register_blueprint(web)
manage.py
from flask_crm2 import app if __name__ == '__main__': app.run()
三 扩展
3.1 特殊装饰器的使用
我们以before_request为例进行说明:
全局使用
from flask import Flask # 导入蓝本 from .views.account import account from .views.user import user app = Flask(__name__) # 全局使用before_request @app.before_request def x1(): print('app.brfore request') # 把蓝本注册到app中 app.register_blueprint(account) app.register_blueprint(user)
单独使用
from flask import Blueprint,render_template account = Blueprint('account',__name__) # 自定义静态文件,模板文件路径,系统会优先在templates,static中寻找,没有则在指定的路径中寻找 # account = Blueprint('account',__name__,template_folder='xxx') # 单独使用before_request @account.before_request def x1(): print('app.brfore request') @account.route('/login') def login(): # 视图函数的名字不能和蓝本对象的名字一致 return render_template('login.html') @account.route('/logout') def logout(): return 'Logout'
3.2 子域名
蓝本子域名:xxx = Blueprint(xxx, __name__, subdomain='admin') # 前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'joe1991.com:5000' # 访问时:admin.'joe1991.com:5000/login
以小型应用举例:
account.py
from flask import Blueprint,render_template account = Blueprint('account',__name__,subdomain='admin') @account.route('/login') def login(): return render_template('login.html') @account.route('/logout') def logout(): return 'Logout'
__init__.py
from flask import Flask # 导入蓝本 from .views.account import account from .views.user import user app = Flask(__name__) app.config['SERVER_NAME'] = 'joe1991.com:5000' # 把蓝本注册到app中 app.register_blueprint(account) app.register_blueprint(user,url_prefix = '/api')
访问效果:
四 其他补充
4.1 一个完整的应用结构
flask_blog ├─app/ # Flask应用一般保存在名为app的包中,包括所有代码、模板、静态文件,可以改为其他名字 │ │ xxx.py # 其他文件,比如:电子邮件支持函数等 │ │ models.py # 数据库模型 │ │ __init__.py # 应用的构造文件,应用的工厂函数就在构造文件中定义,注册蓝本也在此完成 │ │ │ ├─auth/ # 蓝本auth │ │ │ forms.py # 蓝本auth中定义的表单程序 │ │ │ views.py # 蓝本auth中定义的应用路由 │ │ │ __init__.py # 创建蓝本 │ │ │ ├─main/ # 蓝本main │ │ │ errors.py # 蓝本main中定义的错误处理程序 │ │ │ forms.py # 蓝本main中定义的表单程序 │ │ │ views.py # 蓝本main中定义的应用路由 │ │ │ __init__.py # 创建蓝本 │ ├─static/ # 存放静态文件 │ ├─templates/ # 存放模板文件 ├─tests/ # 单元测试在tests包中编写 │ │ test_basics.py │ │ __init__.py │ ├─migrations/ # 数据库迁移脚本在该文件夹中 ├─venv/ # Python虚拟环境在该文件夹中 ├─requirements.txt # 列出所有的依赖包,便于在其他计算机中重新生成相同的虚拟环境 │ # 该文件可由pip自动生成:pip freeze >requirements.txt │ # 如果想创建这个虚拟环境的完整副本,先创建一个新的虚拟环境,然后在其中运行:pip install -r requirements.txt ├─blog_run.py # 主脚本(定义Flask应用实例,同时还有一些辅助管理应用的认为) ├─config.py # 存储配置
4.2 虚拟环境
安装Flask最便捷的方法就是使用虚拟环境。何为虚拟环境?虚拟环境是Python解释器的一个私有副本,在这个环境中我们可以安装私有包,而且不会影响系统中安装的全局Python解释器。
虚拟环境非常有用,可以避免我们安装的Python版本和包与系统预装的发生冲突,为每个项目单独创建虚拟环境,可以保证应用只能访问所在虚拟环境中的包,从而保持全局解释器的干净整洁,使其只作为创建更多虚拟环境的源。与直接使用系统全局的Python解释器相比,使用虚拟环境还有个好处,那就是不需要管理员权限。
4.2.1 如何在Python3中创建虚拟环境?
Python和Python2解释器创建虚拟环境的方法有所不同。在Python3中,虚拟环境由Python标准库中的venv包原生支持。
如果是Ubantu Linux系统预装的Python3,那么标准库中没有venv包,则我们需要先安装python3-venv包:
$ sudo apt-get install python3-venv
然后再创建虚拟环境,命令格式如下:
$ python3 -m venv virtual-environment-name
-m venv选项的作用是以独立的脚本运行标准库中的venv包,后面的参数为虚拟环境的名称。
如果我们需要在xxx目录中创建一个虚拟环境,如下操作(我们需要确保当前目录是xxx):
$ python3 -m venv venv
这个命令执行完成后,xxx目录中会出现一个名为venv的子目录(通常虚拟环境的名称为venv,我们也可以修改为其他名称),这就是一个全新的虚拟环境,包含这个项目专用的Python解释器。
4.2.2 如何在Python2中创建虚拟环境?
python2中没有集成venv包。这一版解释器需要使用第三方工具virtualenv创建虚拟环境。同样的需要确保在特定文件夹中(比如:xxx),然后根据自己的操作系统,执行操作。
如果是Linux或MacOS,执行命令:
$ sudo pip install virtualenv
如果是win,以“管理员身份运行”打开终端,执行命令:
$ pip install virtualenv
virtualenv命令的参数是虚拟环境的名称,确保当前目录是xxx,然后执行下述命令创建名为venv的虚拟环境:
$ virtualenv venv
这个命令在当前目录中创建一个名为venv的子目录,虚拟环境相关的文件都在这个子目录中。
4.2.3 使用虚拟环境
若想使用虚拟环境,要先将其激活。如果是Linux或MacOS,执行命令:
$ source venv/bin/activate
如果是win,执行命令:
$ venv\Scripts\activate
虚拟环境被激活后,里面的Python解释器的路径会被添加到当前命令会话的PATH环境变量中,指明在什么位置寻找一众可执行文件。为了提醒以激活虚拟环境,激活虚拟环境的命令会修改命令提示符,加入环境名:
(venv) $
激活虚拟环境后,在命令提示符中输入python,将调用虚拟环境中的解释器,而不是系统全局解释器。如果同时打开多个命令提示符窗口,每个窗口都需要激活。
虚拟环境中的工作结束后,在命令提示符中输入deactivate,还原当前终端会话的PATH环境变量,把命令提示符重置为最初的状态。
补充说明:不激活也可以使用虚拟环境:
# 在Linux或MacOS执行 venv/bin/python, # 在win中执行 venv\Scripts\python
一个小知识点:任何时候我们可以通过pip freeze命令查看虚拟环境中安装了那些包。
4.3 Web开发服务器
Flask应用自带Web开发服务器,通过flask run命令运行。这个命令在FLASK_APP环境变量指定的Python脚本中寻找应用实例。
若我们想执行上面的应用,首先确保之前创建的虚拟环境已激活,而且里面安装了Flask。 Linux或MacOS用户执行下述命令启动Web服务器:
(venv) $ export FLASK_APP = blog_run.py (venv) $ flask run
如果是win,则执行如下命令:
(venv) $ set FLASK_APP = blog_run.py (venv) $ flask run
服务器启动后便开始轮询,处理请求。直到按Ctrl+C键停止服务器,轮询才结束。
补充说明:Flask提供的Web服务器只适用于开发和测试。
Flask Web开发服务器也可以通过编程的方式启动:
if __name__ == '__main__':
app.run()调试模式
Flask应用可以在调试模式中运行。在这个模式下,开发服务器默认会加载两个便利的工具:重载器和调试器。
调试模式默认禁用,如果想启用,在flask run之前需先设定FLASK_DEBUG=1环境变量。
如果想以编程的方式启动调试模式,就使用app.run(debug=1)。
4.4 命令行选项
flask命令支持一些选项。执行flask --help,或者执行flask而不提供任何参数,可以参看那些选项可用:
(venv) $ flask --help
Usage: flask [OPTIONS] COMMAND [ARGS]...
...
> set FLASK_APP=hello.py
> flask runOptions: --version Show the flask version --help Show this message and exit. Commands: db Perform database migrations. routes Show the routes for the app. run Runs a development server. shell Runs a shell in the app context.
flask shell命令在应用的上下文中打开一个python shell会话。在这个会话中可以运行维护任务或测试,也可以调试问题。
(venv) $ flask run --help
Usage: flask run [OPTIONS]
Run a local development server.
...
Options:
-h, --host TEXT The interface to bind to.
-p, --port INTEGER The port to bind to.
--cert PATH Specify a certificate file to use HTTPS.
--key FILE The key file to use when specifying a
certificate.
--reload / --no-reload Enable or disable the reloader. By default
the reloader is active if debug is enabled.
--debugger / --no-debugger Enable or disable the debugger. By default
the debugger is active if debug is enabled.
--eager-loading / --lazy-loader
Enable or disable eager loading. By default
eager loading is enabled if the reloader is
disabled.
--with-threads / --without-threads
Enable or disable multithreading.
--help Show this message and exit.--host参数特别有用,它告诉Web服务器在那个网络接口上监听客户端发来的连接。默认情况下,Flask的Web服务器监听localhost上的连接,因此服务器只接收运行服务器的计算机发送连接。下述命令让Web服务器监听公共网络接口上的连接,因此同一网络中的其他计算机发送的连接也可以接收到:
(venv) $ flask run -- host 0.0.0.0
如果想以编程的方式实现,就使用:
app.run(host=’0.0.0.0’)




浙公网安备 33010602011771号