最近接触python的Web开发,在Flask轻框架下使用Blueprint实现模块化,本来就对这个框架接触不久,Blueprint实现模块化上网找了一些教程,各种尝试出现各种各样的问题,网上的教程大多千篇一律没有参考性,也解决不了我的实际问题,我关注的点都跳过了,实则无奈自己摸索了一番写一篇简单教程吧,希望能帮到有需要的。
吐槽完了开始进入正题。
——————————————————————————————————————————————————
开发环境:
windows10、pycharm、python 3.7
功能需求:
(1)用户登录注册
(2)用户信息显示跟编辑
要先了解的一些概念:
(1)__init__.py 文件的作用:该文件存放的文件夹会当成模块来使用,可以统一导入一些包,避免循环引用。
(2)蓝图(Blueprint)第一个参数相当于命名空间,可以避免同函数名调用的冲突。你懂的。
about_opt = Blueprint('about_opt', __name__, static_folder="../static",template_folder="../templates")
第二个参数填__name__就可以了,表示当前模块。
static_folder 是当前模块依赖的静态文件所在的文件夹,就是告诉框架去哪找图片,脚本等资源。
template_folder 存放页面模板的文件夹。
(3)项目的统一配置文件config.py
import os
class Config(object):
SESSION_TYPE = 'filesystem'
CSRF_ENABLED = True # CSRF_ENABLED 配置是为了激活 跨站点请求伪造 保护
SECRET_KEY = os.urandom(24) #SECRET_KEY 配置仅仅当 CSRF 激活的时候才需要,它是用来建立一个加密的令牌,用于验证一个表单。
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:root@localhost:3306/bigdata?charset=utf8'
SQLALCHEMY_TRACK_MODIFICATIONS = False
定义了一些常用的变量,在app初始化实例的时候加载
app = Flask(__name__, static_folder="static", template_folder="templates")
app.config.from_object(Config)
项目使用的主要模块:
Flask-Login==0.4.1 登录模块
Flask-Migrate==2.5.2 ORM数据库映射模块
Flask-Session==0.3.1
Flask-SQLAlchemy==2.4.0 MySQL支持模块,数据保存
Flask-WTF==0.14.2 表单模块
整个项目的结构:
每一个模块都按照标准的文件目录构建的
重点关注每一个模块都有一个__init__.py文件,除了把文件夹当成模块处理外,还可以用来创建蓝图实例,下面会涉及。
routes.py 定义路由的地方
models.py 相当于Java里面的Bean
form.py 表单类
error.py 错误处理重定向路由
每一个模块都有static跟templates文件夹,可以单独存放也可以放到公共的一个文件夹,在蓝图实例初始化的时候指定。
下面进入代码部分(只关注重点部分,详细内容请看源码)
一、模板继承
有时候页面有些部分是可以重复使用的,我们把它抽出来直接单独一个文件。
例如:例子中的页面顶部导航栏抽象出来base.html,在需要的地方引入即可{% extends 'base.html' %}。
base.html页面要填充的内容表示为:
{% block content %}
{#页面内容#}
{% endblock %}
引用的地方声明填充的内容为{% block content %}{% endblock %}包裹的内容。
index.html
{% extends 'base.html' %}
{% block content %}
<h1>你好呀, {{ current_user.username }} !</h1>
{% for post in posts %}
<div><p>{{ post.author.username }} 说:<b>{{ post.body }}</b></p></div>
{% endfor %}
{% endblock %}
二、模版重用
对于重复使用的页面组件可以抽出来单独一个文件,使用{% include '_post.html' %}插入其它要使用的页面。
例如:user.html 页面引用另外一个模板文件的内容
{% for post in posts %}
{% include '_post.html' %}
{% endfor %}
三、Flask初始化配置
我把Flask初始化的代码放在SimpleLogin\main\__init__.py,main模块作为整个项目的主模块。
例子中需要配置数据库,Session,登录模块。一些常量单独定义在config.py文件了,所以代码中注释掉了。
app = Flask(__name__, static_folder="static", template_folder="templates")
# 从配置类中初始化
app.config.from_object(Config)
# session配置
# app.config['SESSION_TYPE'] = 'filesystem'
# app.config['SECRET_KEY'] = os.urandom(24)
Session(app)
# 数据库配置
# app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost:3306/bigdata?charset=utf8'
# app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 绑定app和数据库,以便进行操作
migrate = Migrate(app, db)
# 登录配置
login_manager = LoginManager(app)
# 登录页面名称
login_manager.login_view = 'login'
# 用户验证处理user_loader实现
from login.models import User
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
四、Blueprint使用
在每一个模块定义一个Blueprint实例,可以单独放一个文件也可以放在__init__.py文件中初始化。
例子是统一在__init__.py文件中初始化
about_opt = Blueprint('about_opt', __name__, static_folder="../static",
template_folder="../templates")
import about.routes,about.errors
login_opt = Blueprint('login_opt', __name__, static_folder="../static", template_folder="../templates")
import login.routes
main_opt = Blueprint('main_opt', __name__, static_folder="../static", template_folder="../templates")
import main.routes
记得在最后要import当前模块的路由相关的文件。
最后在app初始化完之后注册Blueprint
app.register_blueprint(login_opt)
app.register_blueprint(about_opt)
app.register_blueprint(main_opt)
在当前模块的路由要使用对应声明的蓝图实例名:@蓝图实例名.route
...\SimpleLogin\login\routes.py
@login_opt.route('/login', methods=['GET', 'POST'])
def login():
...\SimpleLogin\about\routes.py
@about_opt.route('/user/<username>')
@login_required # 需要登录验证
def user(username):
在使用url_for的时候要加上蓝图的命名空间url_for('login_opt.login')
五、登录处理
在Flask实例创建之后作为参数初始化LoginManager对象。
使用装饰器实现user_loader处理逻辑
# 登录配置
login_manager = LoginManager(app)
login_manager.login_view = 'login'
from login.models import User
@login_manager.user_loader
def load_user(id):
return User.query.get(int(id))
在需要登录验证的路由添加@login_required即可。
@about_opt.route('/user/<username>')
@login_required # 需要登录验证
def user(username):
user = User.query.filter_by(username=username).first_or_404()
posts = [
{'author': user, 'body': '测试Post #1号'},
{'author': user, 'body': '测试Post #2号'}
]
return render_template('user.html', user=user, posts=posts)
总结:
一开始flask实例化的代码没有在main模块的__init__.py文件中,是放在app.py文件的,因为app.py文件不是放在模块文件夹下,其它地方引用在app.py文件中初始化的实例时遇到很多问题,最后把初始化的内容放在单独的一个main模块__init__.py文件中,其它引用到main模块中初始化的实例可以使用from main import xx 的形式导入。
详细的代码请看源码
项目源码地址:https://github.com/StarsAaron/SimpleLogin-Blueprint/tree/master