用 Flask 来写个轻博客 (17) — MV(C)_应用蓝图来重构项目

简介: 目录目录前文列表重构目录结构重构代码使用蓝图后的路由过程总结前文列表用 Flask 来写个轻博客 (1) — 创建项目 用 Flask 来写个轻博客 (2) — Hello World! 用 Flask 来写个轻博客 (3) — (M)...

目录

前文列表

用 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 中:蓝图是为了让整个项目更具模块化,引入了组件的思想,使得一个项目就像是由多个组件组合起来的一样。符合松耦合的设计思想,极大的提高了项目的扩展能力和便于合作开发。在这个项目中引入蓝图是为了以后添加后台管理组件、用户登陆组件等所做的准备。

相关文章
|
4月前
|
监控 测试技术 Docker
【步步惊心】Flask应用云端之旅:从本地调试到一键上线的终极秘籍!
【8月更文挑战第31天】本文详细介绍了将基于Flask框架的Web应用从本地开发环境部署到云平台的全过程。首先,通过示例代码展示了如何搭建本地环境并测试应用。接着,讲解了如何使用Docker构建生产环境镜像。最后,以Heroku为例,说明了如何将应用部署到云平台,并介绍了监控与维护的方法。通过本文的最佳实践,你可以轻松完成Flask应用的部署。
57 0
|
19天前
|
监控 安全 测试技术
正确配置Flask以提高应用的安全性
正确配置Flask以提高应用的安全性
82 49
|
2月前
|
前端开发 JavaScript 中间件
七、Flask蓝图使用之七
七、Flask蓝图使用之七
44 0
|
4月前
|
数据可视化 前端开发 数据挖掘
【优秀python大屏】基于python flask的广州历史天气数据应用与可视化大屏
本文介绍了一个基于Python Flask框架的广州历史天气数据应用与可视化大屏系统,该系统通过数据采集、处理、分析和可视化技术,提供了丰富的气象数据展示和决策支持,帮助用户快速了解和应对气象变化。
111 3
【优秀python大屏】基于python flask的广州历史天气数据应用与可视化大屏
|
4月前
|
存储 Linux 开发工具
【Azure App Service】本地Git部署Python Flask应用上云(Azure App Service For Linux)关键错误
【Azure App Service】本地Git部署Python Flask应用上云(Azure App Service For Linux)关键错误
|
4月前
|
存储 SQL 安全
【绝密攻略】Flask应用如何抵御黑客入侵?七大安全技巧助你构建固若金汤的Web防线!
【8月更文挑战第31天】安全性是Web应用开发中的关键部分。Flask作为一款轻量级且高度可定制的框架,虽灵活但需开发者确保应用安全。本文介绍如何通过具体措施加固Flask应用,包括更新依赖项、启用CSRF保护、使用HTTPS、安全存储密码、防止SQL注入及清理用户输入等。通过示例代码展示如何在实际开发中应用这些策略,帮助提升应用安全性,为用户提供更可靠的服务。
120 0
|
4月前
|
Linux Python
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
【Azure 应用服务】Azure App Service For Linux 上实现 Python Flask Web Socket 项目 Http/Https
|
4月前
|
Python Windows 内存技术
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
【Azure 应用服务】Azure App Service (Windows) 使用Flask框架部署Python应用,如何在代码中访问静态文件呢?如何设置文件路径?是相对路径还是绝对路径呢?
|
5月前
|
安全 前端开发 API
震惊!掌握Django/Flask后,我竟然轻松征服了所有Web项目难题!
【7月更文挑战第15天】Python Web开发中,Django以其全面功能见长,如ORM、模板引擎,助你驾驭复杂需求;Flask则以轻量灵活取胜,适合快速迭代。两者结合使用,无论是数据库操作、用户认证还是API开发,都能让你应对Web挑战游刃有余。掌握这两者,Web项目难题变得易如反掌!
80 10
|
5月前
|
存储 数据库 开发者
Flask中的蓝图与插件应用:构建模块化Web应用的利器
【7月更文挑战第19天】Flask蓝图和插件是构建模块化、可扩展和可维护Web应用的强大工具。蓝图允许你将应用分割成多个独立的部分,提高了代码的组织性和可重用性;而插件则为Flask应用提供了丰富的功能和社区支持,简化了开发过程。通过合理地使用蓝图和插件,你可以更加高效地开发出高质量的Web应用。