1 Flask简介
Flask诞生于2010年,是Armin ronacher(阿明·罗纳彻)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架。
Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现。比如可以用 Flask 扩展加入ORM、窗体验证工具,文件上传、身份验证等。Flask 没有默认使用的数据库,你可以选择 MySQL,也可以用 NoSQL。
flask的 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2。Itsdangrous(token加密模块),Click(终端命令管理工具),flask内核本身,这5个核心模块组成 Flask 框架
1.1 Flask中的实现方式
在Flask框架中,MVC和MTV的实现方式有所不同:
- MVC:Flask本身不直接支持MVC模式,但可以通过自定义路由和函数来实现类似的功能。模型通常使用SQLAlchemy等ORM工具,视图通过路由和函数处理请求,控制器功能通过函数调用模型和视图完成。
- MTV:Flask默认使用MTV模式。模型使用SQLAlchemy等ORM工具处理数据,视图通过路由和函数处理请求,模板负责HTML页面的渲染。视图从模型获取数据,然后传递给模板进行展示
Flask本身不强制严格遵循MVC,是一种"微框架",更强调灵活性,开发者可以自由组织项目结构,将Controller、Model、View合理分离或混合使用。
1.2 Flask安装
若是要直接使用Flask,直接使用python的包管理工具pip进行安装,在终端使用pip install flask
即会下载安装最新版本的Flask,这样就在本地的python包里面安装上了Flask,在学习阶段这样操作是没有任何问题的,但是若是后续因为不同的需求,而导致所需的依赖版本和我们自己本地的不同,使用本地的环境就会出现依赖冲突,所以会使用到虚拟环境进行开发,后续会介绍虚拟环境的配置。
2 Flask项目创建
Flask的创建方式是比较方便的,我们可以通过新建python脚本来实现一个简易Flask项目的创建,Flask特点就是小巧,只需要简单的几行代码即可提供一个 API。首先新建一个app.py,内容如下:
python
# 首先从flask模块中导入Flask类
from flask import Flask
# 使用Flask类创建一个app对象
# __name__代表当前app.py这个脚本
app = Flask(__name__)
# 创建一个路由和视图函数的映射
@app.route("/")
def index():
# flask 默认支持函数式视图,视图的函数名不能重复,否则报错
# 视图的返回值将被flask包装成响应对象的HTML文档内容,返回给客户端
return 'hello flask'
if __name__ == '__main__':
app.run()
3 项目配置
3.1 debug模式
在我们的开发过程中,时常需要检查我们写的功能是否有用,比如上述的视图函数返回给前端页面的hello flask
被修改了,若要查看改动是否成功,则需要关闭该项目,再重新启动才能看到效果,这样是非常不方便的,这是因为Flask默认是关闭debug模式的,就需要重新启动项目才能看到我们对项目内容的修改,所以需要就爱那个debug改为True。debug模式的配置方式有多种:
python
"""flask项目加载站点配置:方式一"""
# app.config["配置项"] = 配置项值
# app.config["DEBUG"] = False
"""flask项目加载站点配置:方式二"""
# app.config是整个flask项目默认的配置属性,里面包含了所有的可用配置项,配置项的属性名都是大写字母或大小字母+下划线组成
# config = {
# "DEBUG": True
# }
# app.config.update(config)
"""flask项目加载站点配置:方式三"""
# from settings import Setting
# app.config.from_object(Setting)
# settings.py
# class Setting:
# DEBUG = True
"""flask项目加载站点配置:方式四"""
# app.config.from_pyfile('settings.py')
# settings.py:
# DEBUG = True
"""flask项目加载站点配置:方式五"""
# app.run(dubuge = True)
3.2 Host以及Port
Host代表的是主机,Port代表的是端口号,这里举一个简单的例子来简单解释Host和Port。我们经常用的百度首页的网址为:https://www.baidu.com:443,其中冒号前面的www.baidu.com就是Host,冒号后面的443就是端口号,百度首页网站使用了https协议,因为https协议默认监听的是443端口,若是没有使用https协议而是http协议的网站默认是80端口,所以在访问百度首页的网址时,即使不用指定443端口,浏览器也会自动请求百度的443端口。我们的项目运行后显示访问的地址为127.0.0.1:5000
,其中127.0.0.1
表示本机或本地节点,5000
为端口号,简单来说,别人无法通过该网址访问我们的项目,将host修改为0.0.0.0
,终端输出信息就会多一个地址:
这时我们可以用同一局域网下的其他设备访问该地址查看我们的项目,简单来说,我的电脑连着手机WiFi,项目启动后,手机也可以访问该地址。
而我们的项目默认使用5000端口,若是该端口被其它进程占用了,项目就无法正常启动和,这时就需要更改为其它端口。
python
# 导入flask核心类
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
@app.route("/")
def index():
return '你好'
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80)
4 路由
路由是绑定应用程序(视图)和url地址的一种一对一的映射关系!我们在开发过程中,编写项目时所使用的路由往往是指代了框架/项目中用于完成路由功能的类,这个类一般就是路由类,简称路由。
在我们上面的代码中,有一个装饰器@app.route('/')
,这是Flask 中用来定义路由的装饰器,意思是当用户访问网站根路径 '/'
时,执行对应的函数。具体来说:
'/'
表示网站的主页路径。@app.route('/')
把这个路径绑定到后面定义的函数上。- 访问
http://服务器地址/
时,就会调用这个函数,返回对应的内容(如HTML页面或数据)。
在我们上面的例子中,访问http://127.0.0.1:5000/
时,Flask根据该地址找到对应的视图函数并执行,然后就爱那个返回结果传递到前端,这时浏览器就会解析后端返回的内容解析之后显示给用户查看。
若是我们新添加如下内容:
python
# 导入flask核心类
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
@app.route("/")
def index():
return '你好'
@app.route("/profile")
def profile():
return '个人中心页面'
if __name__ == '__main__':
app.run()
项目启动后通过浏览器访问如下地址即可得到不同的内容。

4.1 路由查询参数
查询参数是附在URL末尾的键值对,以问号开头(固定格式),如下图我们在使用百度进行搜索时,wd=图片
就是查询参数。

在flask中,我们可以通过request.args
来获取这些参数。例如:
python
from flask import Flask, request
app = Flask(__name__)
@app.route('/search')
def search():
query = request.args.get('wd')
print(request.args) # 查看请求参数内容
return f"搜索内容为:{query}"
if __name__ == '__main__':
app.run(debug=True)
若我们想要在页面内进行内容搜索,启动项目后通过地址+/search?wd=查询关键字
来进行页面查询,只不过此处没有具体的功能实现。
4.2 路由变量参数
路由变量参数则是嵌入在URL路径中的动态部分,程序中用尖括号<>来包围,例如/user/中的变量username
会被传递给视图函数作为参数。
python
from flask import Flask
app = Flask(__name__)
@app.route('/user/<username>')
def show_user(username):
return f"用户名为:{username}"
在上面的例子中,传递的username
为字符串类型数据,将其return之后前端访问127.0.0.1:5000/user/字符串内容------用户名
就会显示用户名为:对应的字符串
。
在我们的实际应用中,可能需要传递其他类型的参数,在我们的图书管理等系统当中,可能图书的序号为整数,想要进入到某本书的详情页,在传递参数变量时限定为整数,就可以用<int:56>(假设想要进入到图书序号为56的图书详情页)
,在限定了参数类型之后,我们传递其他类型的参数是无法访问页面的,比如传递float型的数字到限定为整数类型的路由中就无法将参数传递到视图函数执行程序。
以下是flask中路由变量参数的几种类型:
转换器名称 | 描述 |
---|---|
string | 默认类型,接受不带斜杠的任何文本 |
int | 接受正整数 |
float | 接受正浮点值 |
path | 接收string 但也接受斜线 |
uuid | 接受UUID(通用唯一识别码)字符串 xxxx-xxxx-xxxxx-xxxxx |
4.3 查询参数和变量参数结合
python
from flask import Flask, request
app = Flask(__name__)
# 查询参数
@app.route('/search')
def search():
query = request.args.get('wd')
print(request.args)
return f"搜索内容为:{query}"
# 变量参数
@app.route('/book/<int:book_id>')
def book(book_id):
return f'图书序号为:{book_id}'
# 两者结合
@app.route('/book_query/<string:book_name>')
def book_query(book_name):
book_id = request.args.get('book_id')
return f"图书名称为{book_name},图书id为{book_id if book_id else None}"
if __name__ == '__main__':
app.run(debug=True)
在@app.route('/book_query/<string:book_name>')
中,我们可以只通过book_name
访问图书详情页查看书籍,但是若有同名的书籍就显得不够严谨,所以我们需要增加book_id
来确定是哪一本书籍,这时我们只需要访问http://127.0.0.1:5000/book_query/平凡的世界?book_id=12
即可得到名为平凡的世界
,序号为12
的书籍详情页。
4.4 自定义路由参数转换器
自定义路由参数转换器也叫正则匹配路由参数,在 web 开发中,可能会出现限制用户访问规则的场景,而原本flask提供的数据类型限制无法满足更为复杂的需求,比如需要进行邮箱的匹配,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问(规范格式)
具体实现步骤为:
- 导入转换器基类BaseConverter:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录
- 自定义转换器:自定义类继承于转换器基类BaseConverter
- 添加转换器到默认的转换器字典DEFAULT_CONVERTERS中
- 使用自定义转换器实现自定义匹配规则
代码实现
- 导入转换器基类
python
from werkzeug.routing.converters import BaseConverter
- 自定义转换器
python
class RegexConverter(BaseConverter):
def __init__(self, map, *args, **kwargs):
super().__init__(map, *args, **kwargs)
self.regex = args[0]
- 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re
python
app.url_map.converters["re"] = RegexConverter
- 使用转换器去实现自定义匹配规则,此处定义的规则是:手机号码
python
from flask import Flask
app = Flask(__name__)
app.config["DEBUG"] = True
# [在实际项目开发中,会单独准备一个python文件来保存转换器的定义代码]
# 自定义路由转换
from werkzeug.routing.converters import BaseConverter
# 1. 自定义路由转换器
class MobileConverter(BaseConverter):
"""手机号参数类型转换器"""
regex = r"1[3-9]\d{9}"
# 2. 将自定义路由转换器类注册到flask项目中
app.url_map.converters["mob"] = MobileConverter
# 3. 使用自定义路由转换器
@app.route("/sms/<mob:mobile>")
def sms(mobile):
return "发送短信给手机号:{}的用户".format(mobile)
if __name__ == '__main__':
app.run()
如果访问的url不符合规则,会提示找不到页面