目录

前文列表

用 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。EG url_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 classtables 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 classValidation 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)_应用蓝图来重构项目的更多相关文章

  1. 用 Flask 来写个轻博客 (16) — MV(C)_Flask Blueprint 蓝图

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 Blueprint 蓝图 定义一个蓝图 注册一个蓝图 创建蓝 ...

  2. 用 Flask 来写个轻博客

    用 Flask 来写个轻博客 用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)V ...

  3. 用 Flask 来写个轻博客 (37) — 在 Github 上为第一阶段的版本打 Tag

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 第一阶段结语 打 Tag 前文列表 用 Flask 来写个轻博客 (1 ...

  4. 用 Flask 来写个轻博客 (36) — 使用 Flask-RESTful 来构建 RESTful API 之五

    目录 目录 前文列表 PUT 请求 DELETE 请求 测试 对一条已经存在的 posts 记录进行 update 操作 删除一条记录 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 ...

  5. 用 Flask 来写个轻博客 (35) — 使用 Flask-RESTful 来构建 RESTful API 之四

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 POST 请求 身份认证 测试 前文列表 用 Flask 来写个轻博客 ...

  6. 用 Flask 来写个轻博客 (34) — 使用 Flask-RESTful 来构建 RESTful API 之三

    目录 目录 前文列表 应用请求中的参数实现 API 分页 测试 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask 来写个轻博客 (2) - Hello World! 用 F ...

  7. 用 Flask 来写个轻博客 (33) — 使用 Flask-RESTful 来构建 RESTful API 之二

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 构建 RESTful Flask API 定义资源路由 格式 ...

  8. 用 Flask 来写个轻博客 (32) — 使用 Flask-RESTful 来构建 RESTful API 之一

    目录 目录 前文列表 扩展阅读 RESTful API REST 原则 无状态原则 面向资源 RESTful API 的优势 REST 约束 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...

  9. 用 Flask 来写个轻博客 (31) — 使用 Flask-Admin 实现 FileSystem 管理

    Blog 项目源码:https://github.com/JmilkFan/JmilkFan-s-Blog 目录 目录 前文列表 扩展阅读 编写 FileSystem Admin 页面 Flask-A ...

随机推荐

  1. Where should I put <script> tags in HTML markup?

    Where should I put <script> tags in HTML markup? When embedding JavaScript in an HTML document ...

  2. 110、TensorFlow张量值的计算

    import tensorflow as tf #placeholders在没有提供具体值的时候不能使用eval方法来计算它的值 # 另外的建模方法可能会使得模型变得复杂 # TensorFlow 不 ...

  3. Selenium:火狐Try Xpath插件替代Firebug和Firepath

    什么是Xpath? XPath是XML的路径语言,通俗一点讲就是通过元素的路径来查找到这个标签元素. 工具 Xpath的练习建议大家安装火狐浏览器后,下载插件,try path. 在Selenium中 ...

  4. Apache Shiro 会话+缓存+记住我(三)

    1.会话管理SessionDao和SessionManager 1)安装Redis 2)依赖 <dependency> <groupId>redis.clients</g ...

  5. C++中逗号操作符重载的分析

    1,关注逗号操作符重载后带来的变化: 2,逗号操作符: 1,逗号操作符(,)可以构成都好表达式:exp1, exp2, exp3, ..., expN 1,逗号表达式用于将多个表达式连接为一个表达式: ...

  6. redis-3.0.0安装

    redis-3.0.0安装 前言 redis是常用的no-sql数据库,常用于缓存数据,同时,他也可以持久化数据.他是C语言开发的,所以安装的时候需要编译. 单机版redis yum install ...

  7. Python:我可以使用类变量作为线程锁吗?

    我正在考虑使用类变量作为线程锁,因为我不想在全局变量中定义锁并且还想防止死锁.这实际上有用吗?例: import threading class A(object): lock = threading ...

  8. 【翻译自mos文章】oraclepassword管理策略

    oraclepassword管理策略 參考原文: Oracle Password Management Policy (Doc ID 114930.1) 细节: password管理通过使用profi ...

  9. 模仿JQuery封装ajax功能

    需求分析 因为有时候想提高性能,只需要一个ajax函数,不想引入较大的jq文件,尝试过axios,可是get方法不支持多层嵌套的json,post方式后台接收方式似乎要变..也许是我不太会用吧..其实 ...

  10. notepad++编辑软件

    官网:http://notepad-plus-plus.org/ 官网截图(2015/4/29): 版本: Notepad++ 6.7.7 下载地址:http://notepad-plus-plus. ...