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

相关文章
|
21天前
|
缓存 前端开发 JavaScript
flask各种版本的项目,终端命令运行方式的实现
flask各种版本的项目,终端命令运行方式的实现
|
3月前
|
数据可视化 API 开发者
通俗易懂:一步步教你 Flask 项目自动生成 API 文档
Flasgger,作为一款强大的 Flask 扩展,自动从 Flask 应用中提取并生成 OpenAPI 规范文档,配备 SwaggerUI,为开发者提供了一条快捷通道,让 API 的文档编制和交互式测试变得简单易行。Flasgger 的设计原则是简化开发流程,通过与 Flask 框架的无缝整合,让开发者可以更专注于应用逻辑的构建。
|
19天前
|
API 数据库 数据安全/隐私保护
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】Django REST framework (DRF) 是用于构建Web API的强力工具,尤其适合Django应用。本文深入讨论DRF面试常见问题,包括视图、序列化、路由、权限控制、分页过滤排序及错误处理。同时,强调了易错点如序列化器验证、权限认证配置、API版本管理、性能优化和响应格式统一,并提供实战代码示例。了解这些知识点有助于在Python面试中展现优秀的Web服务开发能力。
26 1
|
5月前
|
前端开发 JavaScript 数据库
Flask狼书笔记 | 09_图片社交网站 - 大型项目的架构与需求(2)
9.8 收藏图片 前面已经学习过如何使用关联表来表示多对多关系,缺点是只能表示关系,不能存储数据(如我还想记录下收藏图片的时间戳)。这种情况下,我们可以使用关联模型来表示多对多关系。 在关联模型中,我们将Photo模型与User模型的多对多关系,分离成了User模型和Collect模型的一对多关系,和Photo模型与Collect模型的一对多关系。
88 0
|
19天前
|
SQL 中间件 API
Flask框架在Python面试中的应用与实战
【4月更文挑战第18天】**Flask是Python的轻量级Web框架,以其简洁API和强大扩展性受欢迎。本文深入探讨了面试中关于Flask的常见问题,包括路由、Jinja2模板、数据库操作、中间件和错误处理。同时,提到了易错点,如路由冲突、模板安全、SQL注入,以及请求上下文管理。通过实例代码展示了如何创建和管理数据库、使用表单以及处理请求。掌握这些知识将有助于在面试中展现Flask技能。**
16 1
Flask框架在Python面试中的应用与实战
|
24天前
|
存储 Prometheus 监控
Flask监控与日志记录:掌握应用运行状况
【4月更文挑战第16天】本文介绍了在Flask应用中实现监控和日志记录的方法,以确保应用稳定性和问题排查。推荐使用Prometheus、Grafana、New Relic或Flask-MonitoringDashboard等工具进行监控,并通过Python的logging模块记录日志。监控集成涉及安装配置工具、添加监控代码,而日志管理则需要集中存储和使用分析工具。安全是关键,要防止未授权访问和数据泄露,避免记录敏感信息。监控和日志记录有助于提升应用性能和用户体验。
|
24天前
|
缓存 监控 数据库
Flask性能优化:打造高性能Web应用
【4月更文挑战第16天】本文介绍了提升Flask应用性能的七大策略:优化代码逻辑,减少数据库查询,使用WSGI服务器(如Gunicorn、uWSGI),启用缓存(如Flask-Caching),优化数据库操作,采用异步处理与并发(如Celery、Sanic),以及持续监控与调优。通过这些手段,开发者能有效优化Flask应用,适应大型或高并发场景,打造高性能的Web服务。
|
24天前
|
监控 安全 数据库
Flask应用部署指南:从开发到生产环境
【4月更文挑战第16天】本文是Flask应用从开发到生产的部署指南,涵盖开发环境准备、应用开发、部署方案选择、生产环境配置、应用部署、监控与维护。确保安装Python、Flask及依赖库,使用文本编辑器或IDE编写代码,关注应用安全与性能。选择WSGI服务器、Docker或云服务平台部署,配置生产环境,确保安全性,然后部署应用并进行监控维护,定期更新修复问题,保证应用稳定运行。
|
24天前
|
JSON 安全 API
Flask-Login与Flask-RESTful:扩展你的应用功能
【4月更文挑战第16天】本文介绍了两个实用的Flask扩展——Flask-Login和Flask-RESTful。Flask-Login提供用户认证和会话管理,简化了登录、注销和保护路由的逻辑。而Flask-RESTful则助力构建RESTful API,支持多种HTTP方法和请求解析。通过这两个扩展,开发者能轻松增强Flask应用的功能性,实现安全的用户认证和高效的API交互。
|
24天前
|
数据库 数据安全/隐私保护 开发者
WTForms在Flask中的应用:创建与验证表单
【4月更文挑战第16天】本文介绍了如何在Flask应用中使用WTForms进行表单处理。首先,通过`pip install WTForms`安装库,并在配置文件中启用CSRF保护。接着,创建表单类,如`RegistrationForm`,包含所需字段及验证规则。在视图函数中处理表单提交,验证数据并进行相应操作。最后,在模板中渲染表单,显示标签、输入字段及验证错误信息。WTForms提供便捷的表单创建和验证,增强应用交互性和安全性。