用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目
目录
前文列表
用 Flask 来写个轻博客 (1) — 创建项目
用 Flask 来写个轻博客 (2) — Hello World!
用 Flask 来写个轻博客 (3) — (M)VC_连接 MySQL 和 SQLAlchemy
用 Flask 来写个轻博客 (4) — (M)VC_创建数据模型和表
用 Flask 来写个轻博客 (5) — (M)VC_SQLAlchemy 的 CRUD 详解
用 Flask 来写个轻博客 (6) — (M)VC_models 的关系(one to many)
用 Flask 来写个轻博客 (7) — (M)VC_models 的关系(many to many)
用 Flask 来写个轻博客 (8) — (M)VC_Alembic 管理数据库结构的升级和降级
用 Flask 来写个轻博客 (9) — M(V)C_Jinja 语法基础快速概览
用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法
用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
用 Flask 来写个轻博客 (12) — M(V)C_编写和继承 Jinja 模板
用 Flask 来写个轻博客 (13) — M(V)C_WTForms 服务端表单检验
用 Flask 来写个轻博客 (14) — M(V)C_实现项目首页的模板
用 Flask 来写个轻博客 (15) — M(V)C_实现博文页面评论表单
用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
重构目录结构
现在项目的目录结构:
(env) [root@flask-dev opt]# tree JmilkFan-s-Blog/ -L 1
JmilkFan-s-Blog/
├── config.py
├── env
├── fake_data.py
├── main.py
├── manage.py
├── migrations
├── models.py
├── README.md
├── requirements.txt
├── static
├── templates
├── views.py
└── wt_forms.py
我们会一步一步的将整个项目模块化
创建存放整个模块的文件夹 jmilkfansblog
NOTE: 一般来说这个文件夹的名字应该跟项目的名字一模一样将文件 config.py/models.py 和目录 static/template move 到 jmilkfansblog 目录下
将文件 main.py move 到 jmilkfansblog 目录下并重命名为
__init__.py
,将wt_forms.py
move 到 jmilkfansblog 目录下并重命名为 forms.py创建 jmilkfansblog/controllers 目录,并创建控制器 jmilkfansblog/controllers/blog.py
将 views.py move 成为 jmilkfansblog/controllers/blog.py
现在整个目录结构应该是这样的:
(env) [root@flask-dev JmilkFan-s-Blog]# tree -L 3
.
├── fake_data.py
├── jmilkfansblog
│ ├── config.py
│ ├── controllers
│ │ ├── blog.py
│ │ └── __init__.py
│ ├── forms.py
│ ├── __init__.py
│ ├── models.py
│ ├── static
│ │ ├── css
│ │ ├── fonts
│ │ └── js
│ └── templates
│ ├── blog
│ └── __init__.py
├── manage.py
├── migrations
│ ├── alembic.ini
│ ├── env.py
│ ├── README
│ └── script.py.mako
│ └── versions
│ └── __init__.py
├── README.md
└── requirements.txt
NOET :在现在的目录结构中,存在这大量的 __init__.py
文件,这是当在一个目录结构中存在该文件的话,Python 就会将会该目录解析成为一个包。
重构代码
首先要将所有 move 到 blog 中的模板文件中的
url_for()
函数中的参数修改为url_for('blog.XXX')
或url_for('.XXX')
(当视图函数XXX是属于该模板目录所对应的蓝图时才能使用)。这是因为使用蓝图之后可能会出现多个同名的视图函数,所以 url_for() 函数中的参数必须是 ‘绝对路径’ 才能够正确的返回视图函数所对应的 URL。EGurl_for('blog.home', page=3)
所返回的 URL 为http://127.0.0.1:8089/blog/3
中的/blog/3
,而不是/3
NOTE : 在 blog.py 中的视图函数 home() 的路由装饰器为@blog_blueprint.route('/')
,而不是@blog_blueprint.route('/blog/')
,这是因为创建蓝图对象 blog_blueprint 时,传入 url_prefix 的实参为 ‘/blog’,所以所有装饰器@blog_blueprint.route
的路由 URL 定义会被自动的加入 ‘/blog’ 前缀。这样也便于我们编写同一个蓝图下视图函数的路由代码。将所有的 SQLAlchemy 代码都迁移到 models 模块中,其中包括了 import SQLAlchemy 的相关语句、Model class、tables object 等。
- models.py
from flask.ext.sqlalchemy import SQLAlchemy
# 在 jmilkfansblog/__init__.py 中再初始化 db 对象
db = SQLAlchemy()
posts_tags = db.Table('posts_tags',
db.Column('post_id', db.String(45), db.ForeignKey('posts.id')),
db.Column('tag_id', db.String(45), db.ForeignKey('tags.id')))
class User(db.Model):
"""Represents Proected users."""
...
NOTE : 数据库对象 db 的初始化不能再在 models 模块中进行,因为如果在该模块中导入 app 对象,很可能会造成将所有的的情况,所以我们将初始化 db 对象的代码实现在了 jmilkfansblog/__init__.py 中。
将所有的 WTForm 代码都迁移到 forms 模块中,其中包括了 所有的 Form class、Validation function 等。直接将 wt_forms.py 重命名为 forms.py 就可以了
将 jmilkfansblog/controllers/blog.py 定义成为一个表示博客展示页功能(表现层)组件的 Flask Blueprint,需要把 views 模块中所有的 路由函数、视图函数、sidebar_data() 等都迁移到 blog 模块中,实际上我们可以
mv views.py jmilkfansblog/controllers/blog.py
然后再做修改:- blog.py
from uuid import uuid4
from os import path
from datetime import datetime
from flask import render_template, Blueprint
from sqlalchemy import func
from jmilkfansblog.models import db, User, Post, Tag, Comment, posts_tags
from jmilkfansblog.forms import CommentForm
blog_blueprint = Blueprint(
'blog',
__name__,
# path.pardir ==> ..
template_folder=path.join(path.pardir, 'templates', 'blog'),
# Prefix of Route URL
url_prefix='/blog')
def sidebar_data():
"""Set the sidebar function."""
...
NOTE:现在当我们需要为这个 blog Application 添加一个新的蓝图时,我们只需要在 jmilkfansblog/controllers/ 目录下新建一个模块文件就可以实现。
再一个,我们需要多 jmilkfansblog/init.py 文件进行重构,该文件应该包含了 app 对象的创建、index()、注册蓝图 等代码。当然我们还要将初始化数据库对象 db
- jmilkfansblog/__init__.py
最后需要修改 manage.py 中的导入语句
from flask import Flask, redirect, url_for
from config import DevConfig
from models import db
from controllers import blog
app = Flask(__name__)
# Get the config from object of DecConfig
app.config.from_object(DevConfig)
# Will be load the SQLALCHEMY_DATABASE_URL from config.py to db object
db.init_app(app)
@app.route('/')
def index():
# Redirect the Request_url '/' to '/blog/'
return redirect(url_for('blog.home'))
# Register the Blueprint into app object
app.register_blueprint(blog.blog_blueprint)
if __name__ == '__main__':
app.run()
NOTE:以往我们还需要在 main.py 中导入视图模块 views 才能够使这些视图函数生效,现在因为我们将蓝图对象注册到了 app 对象中,而且 index()
路由函数还重定向到了 'blog/home()
中 。所以现在我们并不需要将 blog 模块导入到 jmilkfansblog/__init__.py 也能使这些视图函数生效了。
使用蓝图后的路由过程
我们假设现在有人使用浏览器访问 http://127.0.0.1:8089/
:
/
:被jmilkfansblog.__init__:index()
获取,并重定向到/blog/
/blog/
:被jmilkfansblog.controllers.blog.home()
获取,然后渲染并返回jmilkfansblog/templates/blog/home.html
总结
controllers 目录的意义:在 controllers/ 目录下,我们定义的 blog.py 蓝图模块(因为含有蓝图对象,并将视图函数注册到了该蓝图对象中),本质上就是以往的视图模块,主要还是用于控制 HTTP 请求的 URL 路由跳转。在以后的开发过程中,如果需要定义一个新的蓝图,那么我们只需要在该目录下创建一个新的蓝图模块,并将蓝图模块中的蓝图对象注册到应用程序入口 jmilkfansblog/init.py 的 app 对象中就可以了。
将视图函数注册到蓝图中:能够让我们在定义视图函数的路由 URL 的时候更加方便,而且自成一套命名空间,使得 Python 代码更加简洁。但是需要注意的是,我们一般会为一个蓝图准备独立出一个存放其模板文件和静态文件的目录,所以在编写模板文件的时候,一定要注意在
url_for
中使用 全路径 的引用方式。将蓝图注册到 app 中:蓝图是为了让整个项目更具模块化,引入了组件的思想,使得一个项目就像是由多个组件组合起来的一样。符合松耦合的设计思想,极大的提高了项目的扩展能力和便于合作开发。在这个项目中引入蓝图是为了以后添加后台管理组件、用户登陆组件等所做的准备。
用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目的更多相关文章
- 用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Blueprint 蓝图 定义一个蓝图 注册一个蓝图 创建蓝 ...
- 用 Flask 来写个轻博客
用 Flask 来写个轻博客 用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)V ...
- 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 第一阶段结语 打 Tag 前文列表 用 Flask 来写个轻博客 (1 ...
- 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五
目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts 记录进行 update 操作 删除一条记录 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 ...
- 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 POST 请求 身份认证 测试 前文列表 用 Flask 来写个轻博客 ...
- 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三
目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 F ...
- 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...
- 用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一
目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...
- 用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理
Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 编写 FileSystem Admin 页面 Flask-A ...
随机推荐
- 【HTTP】http请求url参数包含+号,被解析为空格
项目技术:Angular 6 问题现象:接口传参的时候,使用 httpClient.post 方法提交数据,字段中包含+号被解析成空格,提交数据错误 解决过程: 1.http请求中包含+号,会被自动解 ...
- jmeter 导入csv数据中json格式数据取值不完整
1.jmeter中添加csv数据文件时,数据是json格式 2.jmeter中执行取值发现只取了一部分 分析原因,json格式数据,中间有逗号,而csv是根据逗号来分割的,这回导致我们取值错位. 解决 ...
- Weblgic安装应用报错:Caused by: com.bea.xml.XmlException: failed to load java type corresponding to e=web-a
文章目录 报错如下 解决: 报错如下 Exception in AppMerge flows' progression 后台日志报错: Caused by: com.bea.xml.XmlExcept ...
- upc组队赛14 Communication【并查集+floyd /Tarjan】
Communication 题目描述 The Ministry of Communication has an extremely wonderful message system, designed ...
- PAT甲级【2019年3月考题】——A1158 TelefraudDetection【25】
Telefraud(电信诈骗) remains a common and persistent problem in our society. In some cases, unsuspecting ...
- 存取cookies
保存: Response.Cookies["OpenID"].Value = wxobj.openid; Response.Cookies["NickName" ...
- python学习那点事---列表生成式实现大小写字母相互转换
题目: 已知列表list=["pYTHON","iS",eASY],要求使用列表生成式实现,生成一个新的列表,要求将大写字母转换为小写字母,小写字母转换为大写字 ...
- C#简单的文件依赖缓存的使用
一,FileCache.aspx页面 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind=& ...
- alpha阶段绩效考核
(按姓氏拼音顺序) (评分还考虑了从开题至今的博客.汇报等工作,但由于太杂乱没法列出) 陈修远 B+ 后端技术踩坑及代码编写 傅泳淦 A- Android端技术踩坑及代码编写 李浩冉 B 后端知识 ...
- 【彩彩只能变身队(第七组)】Alpha版
演示总结 -by 彩彩只能变身组(第七组) Part one:功能简介 教师端——班级主页 教师端——创建班级 教师端——批改作业 教师端——作业上交情况 学生端——班级主页 学生端——作业上传 在开 ...