Web框架——Flask系列之蓝图Blueprint(二十一)

一、为什么学习蓝图?

我们学习Flask框架,是从写单个文件,执行hello world开始的。我们在这单个文件中可以定义路由、视图函数、定义模型等等。但这显然存在一个问题:随着业务代码的增加,将所有代码都放在单个程序文件中,是非常不合适的。这不仅会让代码阅读变得困难,而且会给后期维护带来麻烦。

如下示例:我们在一个文件中写入多个路由,这会使代码维护变得困难。

  from flask import Flask    app = Flask(__name__)    @app.route('/')def index():return 'index'@app.route('/list')def list():return 'list'@app.route('/detail')def detail():return 'detail'@app.route('/')def admin_home():return 'admin_home'@app.route('/new')def new():return 'new'@app.route('/edit')def edit():return 'edit'

问题:一个程序执行文件中,功能代码过多。就是让代码模块化。根据具体不同功能模块的实现,划分成不同的分类,降低各功能模块之间的耦合度。python中的模块制作和导入就是基于实现功能模块的封装的需求。

尝试用模块导入的方式解决: 我们把上述一个py文件的多个路由视图函数给拆成两个文件:app.pyadmin.py文件。app.py文件作为程序启动文件,因为admin文件没有应用程序实例app,在admin文件中要使用app.route路由装饰器,需要把app.py文件的app导入到admin.py文件中。

# 文件app.py
from flask import Flask
# 导入admin中的内容
from admin import *
app = Flask(__name__)@app.route('/')
def index():return 'index'@app.route('/list')
def list():return 'list'@app.route('/detail')
def detail():return 'detail'if __name__ == '__main__':app.run()
# 文件admin.py    
from app import app
@app.route('/')
def admin_home():return 'admin_home'@app.route('/new')
def new():return 'new'@app.route('/edit')
def edit():return 'edit'

启动app.py文件后,我们发现admin.py文件中的路由都无法访问。 也就是说,python中的模块化虽然能把代码给拆分开,但不能解决路由映射的问题
在这里插入图片描述
在这里插入图片描述

二、什么是蓝图?

蓝图:用于实现单个应用的视图、模板、静态文件的集合。

蓝图就是模块化处理的类。

简单来说,蓝图就是一个存储操作路由映射方法的容器,主要用来实现客户端请求和URL相互关联的功能。 在Flask中,使用蓝图可以帮助我们实现模块化应用的功能。

三、蓝图的运行机制:

蓝图是保存了一组将来可以在应用对象上执行的操作。注册路由就是一种操作,当在程序实例上调用route装饰器注册路由时,这个操作将修改对象的url_map路由映射列表。当我们在蓝图对象上调用route装饰器注册路由时,它只是在内部的一个延迟操作记录列表defered_functions中添加了一个项。当执行应用对象的 register_blueprint() 方法时,应用对象从蓝图对象的 defered_functions 列表中取出每一项,即调用应用对象的 add_url_rule() 方法,这将会修改程序实例的路由映射列表。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、蓝图的使用:

  1. 创建蓝图对象。
#Blueprint必须指定两个参数,admin表示蓝图的名称,__name__表示蓝图所在模块
admin = Blueprint('admin',__name__)
  1. 注册蓝图路由。
@admin.route('/')
def admin_index():return 'admin_index'
  1. 在程序实例中注册该蓝图。
app.register_blueprint(admin,url_prefix='/admin')

文件目录:
在这里插入图片描述
程序执行文件/test4/test.py

from flask import Flask
#导入蓝图对象
from login import logins
from user import usersapp = Flask(__name__)@app.route('/')
def hello_world():return 'Hello World!'
#注册蓝图,第一个参数logins是蓝图对象,url_prefix参数默认值是根路由,如果指定,会在蓝图注册的路由url中添加前缀。
app.register_blueprint(logins,url_prefix='')
app.register_blueprint(users,url_prefix='')if __name__ == '__main__':app.run(debug=True)

创建蓝图:/test4/user.py

from flask import Blueprint,render_template
#创建蓝图,第一个参数指定了蓝图的名字。
users = Blueprint('user',__name__)@users.route('/user')
def user():return render_template('user.html')

创建蓝图:/test4/login.py

from flask import Blueprint,render_template
#创建蓝图
logins = Blueprint('login',__name__)@logins.route('/login')
def login():return render_template('login.html')

运行/test4/test.py文件
在这里插入图片描述

五、动态路由示例(作者–图书):

文件目录:Flask_test4/delete.py

from flask import Blueprint,redirect,url_for
app_au = Blueprint('app_au',__name__)
app_bk = Blueprint('app_bk',__name__)from test4 import *@app_au.route('/delete_au<id>')
def delete_au(id):del_au = Author.query.filter_by(id=id).first()db.session.delete(del_au)db.session.commit()return redirect(url_for('index'))@app_bk.route('/delete_bk<id>')
def delete_bk(id):del_bk = Book.query.filter_by(id=id).first()db.session.delete(del_bk)db.session.commit()return redirect(url_for('index'))

文件目录:Flask_test4/test4.py

#coding=utf-8
#目的:创建两个模型类型,实现数据库的连接和数据的操作
from flask import Flask,render_template,request,redirect,url_for
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField,SubmitField
from wtforms.validators import DataRequired
#导入delete文件中的蓝图对象
from delete import app_au,app_bkapp = Flask(__name__)
#对数据库连接的基本设置
app.config['SQLALCHEMY_DATABASE_URI']='mysql://root:mysql@localhost/test0'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
#把应用程序的实例和SQLAlchemy进行关联
db = SQLAlchemy(app)
app.config['SECRET_KEY'] = 'a'#自定义表单,实现数据的输入保存操作
class Append(FlaskForm):author = StringField(validators=[DataRequired()])book = StringField(validators=[DataRequired()])submit = SubmitField(u'提交')#自定义模型类
class Author(db.Model):__tablename__ = 'authors'id = db.Column(db.Integer,primary_key=True)name = db.Column(db.String(32),unique=True)def __repr__(self):return 'author:%s'%self.nameclass Book(db.Model):__tablename__ = 'books'id = db.Column(db.Integer,primary_key=True)info = db.Column(db.String(32),unique=True)def __repr__(self):return 'book:%s'%self.info@app.route('/',methods=['GET','POST'])
def index():au = Author.query.all()bk = Book.query.all()form = Append()if form.validate_on_submit():#从表单中获取数据wtf_au = form.author.datawtf_bk = form.book.data#把数据存入模型类中db_au = Author(name=wtf_au)db_bk = Book(info=wtf_bk)#添加到数据库操作db.session.add_all([db_au,db_bk])db.session.commit()au = Author.query.all()bk = Book.query.all()return render_template('index.html',au=au,bk=bk,form=form)if request.method == 'GET':return render_template('index.html',au=au,bk=bk,form=form)#注册蓝图
app.register_blueprint(app_au)
app.register_blueprint(app_bk)if __name__ == '__main__':    print app.url_mapapp.run(debug=True)

查看蓝图路由:蓝图路由可以分为两块,".“前面的是蓝图名称,”."后面的是视图函数名。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 2207. 字符串中最多数目的子字符串(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的字符串 text 和另一个下标从 0 开始且长度为 2 的字符串 pattern &#xff0c;两者都只包含小写英文字母。 你可以在 text 中任意位置插入 一个 字符&#xff0c;这个插入的字符必须是 pattern[0] 或者 pattern[1] 。注…

指令系统——指令格式(详解)

一、总览 二、指令的定义 指令&#xff08;又称机器指令&#xff09;&#xff1a; 是指示计算机执行某种操作的命令&#xff0c;是计算机运行的最小功能单位。 一台计算机的所有指令的集合构成该机的指令系统&#xff0c;也称为指令集。 注&#xff1a;一台计算机只能执行自己…

MySQL中Index Condition Pushdown(ICP)优化

在MySQL 5.6开始支持的一种根据索引进行查询的优化方式。之前的MySQL数据库版本不支持ICP&#xff0c;当进行索引查询是&#xff0c;首先根据索引来查找记录&#xff0c;然后在根据WHERE条件来过滤记录。在支持ICP后&#xff0c;MySQL数据库会在取出索引的同时&#xff0c;判断…

LeetCode 2208. 将数组和减半的最少操作次数(优先队列)

文章目录1. 题目2. 解题1. 题目 给你一个正整数数组 nums 。每一次操作中&#xff0c;你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。&#xff08;注意&#xff0c;在后续操作中你可以对减半过的数继续执行操作&#xff09; 请你返回将 nums 数组和 至少 减少一半…

指令系统——数据存放、指令寻址(详解)

一、总览 二、数据存放 三、指令寻址 四、小结&#xff1a;

数据库和ORMS:使用Tortoise ORM与数据库通信

文章目录1. 安装环境2. 创建数据库模型3. 设置 Tortoise 引擎4. create5. 查询6. 修改、删除7. 添加关联8. 用Aerich建立数据库迁移系统learn from 《Building Data Science Applications with FastAPI》Tortoise ORM 是一种现代异步 ORM&#xff0c;非常适合 FastAPI项目 1. …

指令系统——数据寻址(1)(详解)

一、总览 二、操作数类型与寻址方式 三、数据寻址 四、立即寻址 立即寻址&#xff1a;形式地址A就是操作数本身&#xff0c;又称为立即数&#xff0c;一般采用补码形式。#表示立即寻址特征。 一条指令的执行&#xff1a;取指令访存1次&#xff0c;执行指令访存0次&#xff0c;暂…

使用 docker 搭建开发环境

作为一个 freelancer&#xff0c;经常能够接到很多的开发工作&#xff0c;这些金主&#xff0c;有喜欢 PHP 的&#xff0c;有习惯撒手不管的&#xff1b;有偏好 sqlite 的&#xff0c;也有喜欢 PG 的&#xff0c;我甚至见过 mysql、PG 一起使用的项目&#xff1b;同一门语言下&…

数据库和ORMS:使用 Motor 跟 MongoDB 通信

文章目录1. 安装2. 创建models3. 连接数据库4. 插入文档5. 查询6. 更新、删除7. 嵌套文档learn from 《Building Data Science Applications with FastAPI》面向文档的数据库&#xff08;如MongoDB&#xff09;不需要预先配置模式 Motor&#xff0c;这是一个用于与 MongoDB 异…

指令系统——数据寻址(2)(详解)

一、总览 二、偏移寻址 基址寻址&#xff1a;将CPU中基址寄存器&#xff08;BR&#xff09;的内容加上指令格式中的形式地址A&#xff0c;而形成操作数的有效地址&#xff0c;即EA&#xff08;BR&#xff09;A。 注&#xff1a;基址寄存器是面向操作系统的&#xff0c;其内容由…

十五、MySQL变量(系统变量、自定义变量)相关知识总结

变量: 系统变量&#xff1a; a.全局变量 b.会话变量 自定义变量&#xff1a; a.用户变量 b.局部变量 一、系统变量 说明&#xff1a;变量由系统定义&#xff0c;不是用户定义&#xff0c;属于服务器层面 注意&#xff1a;全局变量需要添加global关键字&#xff0c;会话变量…

LeetCode 2210. 统计数组中峰和谷的数量

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums 。如果两侧距 i 最近的不相等邻居的值均小于 nums[i] &#xff0c;则下标 i 是 nums 中&#xff0c;某个峰的一部分。 类似地&#xff0c;如果两侧距 i 最近的不相等邻居的值均大于 nums[i] &#xff0c;…

【项目总结】如何获取地图上的所有POI

1. 地图POI数据是什么&#xff0c;有什么用 关于地图数据123&#xff0c;可以参考一下这篇 https://www.zhihu.com/question/21530085/answer/18728706&#xff0c;回答了很多信息&#xff1b;下图是摘自其中&#xff0c;展示了建立一个地图需要的几个图层数据&#xff0c;从底…

十六、MySQL流程控制结构(顺序、分支、循环)详解 强化练习

流程控制结构&#xff1a;顺序、分支、循环 一、分支结构 case结构作为表达式&#xff1a; case结构作为独立的语句&#xff1a; if函数 语法&#xff1a;if(条件,值1&#xff0c;值2) 功能&#xff1a;实现双分支 应用在begin end中或外面 case结构 语法&#xff1a; 情…

LeetCode 2211. 统计道路上的碰撞次数

文章目录1. 题目2. 解题1. 题目 在一条无限长的公路上有 n 辆汽车正在行驶。汽车按从左到右的顺序按从 0 到 n - 1 编号&#xff0c;每辆车都在一个 独特的 位置。 给你一个下标从 0 开始的字符串 directions &#xff0c;长度为 n 。 directions[i] 可以是 ‘L’、‘R’ 或 …

服务端的思考

概述 我们思考发布一个web服务需要做的工作&#xff0c;并进行职责的划分。职责的划分 通常我们会先制定抽象的接口&#xff0c;然后根据接口构造实现类。接口和实现类都完成了&#xff0c;再实施发布。所以&#xff0c;服务端的角色可以划分为&#xff1a;服务接口、服务实现、…

IPv6数据报详解

一、为什么有IPv6&#xff1f; 二、IPv6数据报格式 版本&#xff1a;指明了协议版本&#xff0c;总是6。 优先级&#xff1a;区分数据报的类别和优先级。 流标签&#xff1a;“流”是互联网络上从特定源点到特定终点的一系列数据报。所有属于同一个流的数据报都具有同样的流标签…

LeetCode 2212. 射箭比赛中的最大得分(状态枚举)

文章目录1. 题目2. 解题1. 题目 Alice 和 Bob 是一场射箭比赛中的对手。比赛规则如下&#xff1a; Alice 先射 numArrows 支箭&#xff0c;然后 Bob 也射 numArrows 支箭。 分数按下述规则计算&#xff1a; 箭靶有若干整数计分区域&#xff0c;范围从 0 到 11 &#xff08;…

web前端复习系列[1]——标签

<h1>一般用于网站标题。加入强调语气&#xff0c;使用<strong>和<em>标签。<em> 表示强调&#xff0c;<strong> 表示更强烈的强调。并且在浏览器中<em> 默认用斜体表示&#xff0c;<strong> 用粗体表示。两个标签相比&#xff0c;目…

十七、MySQL触发器(创建、删除、查看)详解

触发器 一、介绍 触发器是与表有关的数据库对象&#xff0c;指在 insert/update/delete 之前或之后&#xff0c;触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作 。 使用别名 OLD 和 NEW 来引用…