文章目录
什么是Flask
在讲什么是Flask之前,我们先了解一下什么是Web Application Framework,Web Application Framework(Web应用程序框架)表示一个库和模块的集合,使Web应用程序开发人员能够编写应用程序,而不必担心协议,线程管理等低级细节。
而Flask是一个用Python编写的Web应用程序框架。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。
安装Flask
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple Flask
一个简单的demo
在这个简单的demo中,我们在浏览器访问http://localhost:5000 ,将在页面显示“Hello World”消息。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello world'
if __name__ == '__main__':
app.run('127.0.0.1',5000,debug = True)
Flask类的构造函数使用当前模块的名称(name)作为参数,创建一个app对象。app对象的route()函数是一个装饰器(而关于python中装饰器的详解,可以参见 python中装饰器详解),它告诉应用程序用户请求哪个URL时应该调用哪个函数启动相应的服务(路由),在这里,URL '/ ’ 将绑定到hello_world()函数,因此,如果用户访问http:127.0.0.1:5000,hello_world()函数的输出将在浏览器中呈现。app对象的add_url_rule()函数也可用于将URL与函数绑定,如以上的demo可进行如下改写:
from flask import Flask
app = Flask(__name__)
def hello_world():
return 'hello world1!'
app.add_url_rule(rule='/', view_func=hello_world)
if __name__ == '__main__':
app.run('127.0.0.1', 5000, debug = True)
再来讲讲Flask中的调试模式,当应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。为避免这种不便,可以启用调试模式。如果代码更改,服务器将自行重新加载。
启动调试模式的方式:
#第一种方式
app.debug = True
app.run()
# 另一种方式
app.run(debug = True)
Flask之动态构建URL
有时我们需要将同一类URL映射到同一个视图函数处理,而在Flask中,可以将URL中的可变部分使用一对小括号<>声明为变量, 并为视图函数传入同名的形参。
from flask import Flask
app = Flask(__name__)
@app.route('/hello/<name>')
def hello_world(name):
return 'Hello %s!' % name
if __name__ == '__main__':
app.run('0.0.0.0', 5000, True)
在上面的示例中,URL规则中的这部分是可变的,Flask将提取用户请求的 URL中这部分的内容,作为视图函数hello_world()的name参数传入。
除了默认字符串作为URL的变量部分之外,还可以使用以下数据类型来构建URL的变量部分:
序号 | 转换器和描述 |
---|---|
1 | int 接受整数 |
2 | float 浮点数 |
如下面代码示例:
from flask import Flask
app = Flask(__name__)
@app.route('/blog/<int:postID>')
def blog(postID):
return 'Blog Number %s!' % postID
@app.route('/price/<float:priceNum>')
def price(priceNum):
return 'Price is %s!' % priceNum
if __name__ == '__main__':
app.run('127.0.0.1', 5000, debug = True)
Flask url_for()
URL反转:根据视图函数名称得到当前所指向的url(视图函数的名称作为第一个参数传入,后续可跟一个或多个关键字参数,每个参数对应于URL的变量部分)
url_for() 函数的用法
- 该函数接受视图函数的名称作为参数,返回对应的url
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/admin')
def hello_admin():
return 'Hello Admin'
@app.route('/guest/<guest>')
def hello_guest(guest):
return 'Hello %s as Guest' % guest
@app.route('/user/<name>')
def hello_user(name):
if name =='admin':
return redirect(url_for('hello_admin'))
else:
return redirect(url_for('hello_guest',guest = name))
if __name__ == '__main__':
app.run(debug = True)
- 还可以用作加载静态文件,例如
//该条语句就是在模版中加载css静态文件.
<link rel="stylesheet" href="{{url_for('static',filename='css/index.css')}}">
Flask HTTP方法
Http协议是万维网中数据通信的基础。在该协议中定义了从指定URL获取数据的不同方法。 下表总结了不同的http方法:
序号 | 方法与描述 |
---|---|
1 | GET 请求指定的页面信息,当需要向服务器传输数据时,是以未加密的形式将数据传输的,最常见的方法。 |
2 | HEAD 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST 向指定网址提交数据进行处理请求(例如提交表单或者上传文件,数据被包含在请求体中),并返回相应响应内容。 |
4 | PUT 向服务器传送数据,并保存到请求URL指定的位置。 |
5 | DELETE 请求服务器删除指定的页面。 |
默认情况下,Flask路由响应GET请求。但是可以通过为route()装饰器提供方法参数来更改此默认选项(@app.route(’/login’,methods = [‘POST’, ‘GET’]))。
Flask 模板
Web模板的诞生是为了将显示与数据分离,让前端工作人员专注表现设计,后台人员注重业务逻辑。模板技术多种多样,但其本质是将模板文件和数据通过模板引擎生成最终的HTML代码。
Flask使用jinga2模板引擎,jinja2是Python的一个流行的模板引擎,它将模板与特定数据源组合以呈现动态网页。
关于Flask中模板的使用,可见这篇博客,写得很详细:Flask入门很轻松(三)—— 模板
Flask静态资源
Web应用程序通常需要静态文件,例如javascript文件或支持网页显示的CSS文件,它将在应用程序的/static
中提供。
在Flask中使用静态资源可见:Flask之静态文件处理
Flask Request对象
来自客户端的数据作为全局请求对象发送到服务器。为了处理这些请求数据,应该从Flask模块导入request:from flask import request。
Request对象的重要属性如下所列:
-
form` - 它是一个字典对象,包含表单参数及其值的键和值对。
-
args` - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
-
Cookies` - 保存Cookie名称和值的字典对象。
-
files` - 与上传文件有关的数据。
-
method` - 当前请求方法。
其详细可见:Flask request 属性详解
下面来讲讲Request对象里的Cookies
Flask Request对象之Cookies
Cookie以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。
Request对象包含Cookie的属性。它是所有cookie变量及其对应值的字典对象,除此之外,cookie还存储其网站的到期时间,路径和域名。
cookie默认只能在主域名下使用,如果我们想要在子域名下使用cookie需要另外设置。
如何在Flask中构造Cookie?在Flask中,服务器对响应对象设置cookie,使用make_response()
函数从视图函数的返回值获取响应对象,之后,使用响应对象的set_cookie()
函数来存储cookie。
如何在Flask中获取Cookie?读回cookie很容易,request.cookies属性的
get()`方法用于读取cookie。
下面来看一个简单的demo
cookie.py
from flask import Flask, redirect, url_for, request, render_template, make_response
app = Flask(__name__)
@app.route('/')
def index():
return render_template('cookie_index.html')
@app.route('/setcookie', methods = ['POST', 'GET'])
def setcookie():
if request.method == 'POST':
user = request.form['nm']
response = make_response(render_template('readcookie.html'))
response.set_cookie('userID', user)
return response
@app.route('/getcookie')
def getcookie():
name = request.cookies.get('userID')
return '<h1>welcome '+ name + '</h1>'
if __name__ == '__main__':
app.run(debug=True)
cookie_index.html
<html>
<body>
<form action = "/setcookie" method = "POST">
<p><h3>Enter userID</h3></p>
<p><input type = 'text' name = 'nm'/></p>
<p><input type = 'submit' value = 'Login'/></p>
</form>
</body>
</html>
readcookie.html
Cookie is set<br/>
<a href='/getcookie'>click to check</a>
Flask Session
与Cookie不同,Session(会话)数据存储在服务器上,需要在该会话中保存的数据会存储在服务器上的临时目录中,Session对象也是一个字典对象,包含会话变量和关联值的键值对。
服务端会为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名,对于此加密,Flask应用程序需要定义一个SECRET_KEY。
有关Flask中Session的操作,可见:Flask操作session
Flask 重定向和错误
重定向
Flask中的redirect()函数调用时,它将用户重定向到具有指定状态代码的另一个目标位置,并返回响应对象,即为重定向。
重定向也分为暂时性重定向(状态码为302)和永久性重定向(状态码为301)
错误
Flask中的abort(code)函数用于提前退出一个请求,并用指定的错误码返回。
errorhandler(code_or_exception):用来监听捕捉异常,然后返回自定义的页面处理,参数code_or_exception –为HTTP的错误状态码或指定异常。
一个小demo
from flask import Flask,abort
app = Flask(__name__)
@app.route('/game/<int:age>')
def play_game(age):
#异常抛出
abort(404)
return "helloworld"
#异常捕获
@app.errorhandler(404)
def page_not_found(e):
print(e)
return "找不到服务器资源,服务器搬家了"
if __name__ == '__main__':
app.run()
Flask 消息闪现
Flask中包含flash()
方法,在视图函数调用flash()函数,传入消息内容,flash()会把消息存储在session中,我们需要在模板中使用全局函数get_flashed_messages()获取消息并将它显示出来。
通过flash()函数发送的消息会存储在session对象中,如果需要把消息加密存储,可以通过设置app.secret_key属性。
Flask 文件上传
Flask 文件上传 在Flask中处理文件上传非常简单。它需要一个HTML表单,其enctype属性设置为“multipart / form-data”,将文件发布到URL。URL处理程序从request.files[]
对象中提取文件,并将其保存到所需的位置。
Flask文件上传中的一些设置
配置 | 描述 |
---|---|
app.config[‘MAX_CONTENT_PATH’] | 指定要上传的文件的最大大小(以字节为单位) |
app.config[‘UPLOAD_FOLDER’] | 定义上传文件夹的路径 |
ALLOWED_EXTENSIONS = set([‘txt’, ‘pdf’, ‘png’, ‘jpg’, ‘jpeg’, ‘gif’]) | 允许的文件扩展名 |
app.config[‘MAX_CONTENT_LENGTH’] = 16 * 1024 * 1024 | 限制文件大小 |
关于文件上传的一个小demo
# -*- coding: utf-8 -*-
import os
from flask import Flask, request, url_for, send_from_directory
from werkzeug import secure_filename
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
#设置文件的上传路径目录
app.config['UPLOAD_FOLDER'] = os.getcwd()
#限制文件大小
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
html = '''
<!DOCTYPE html>
<title>Upload File</title>
<h1>图片上传</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=上传>
</form>
'''
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
file_url = url_for('uploaded_file', filename=filename)
return html + '<br><img src=' + file_url + '>'
return html
if __name__ == '__main__':
app.run()
Flask 扩展
Flask通常被称为微框架,Flask扩展为Flask框架提供了可扩展性。
Flask有大量的Flask扩展可用。Flask扩展是一个Python模块,它向Flask应用程序添加了特定类型的支持,可以通过pip下载所需的扩展。
pip install Flask-Mail
有以下一些常用的扩展
- Flask Mail - 为Flask应用程序提供SMTP接口
- Flask WTF - 添加WTForms的渲染和验证
- Flask SQLAlchemy - 为Flask应用程序添加SQLAlchemy支持
- Flask Sijax - Sijax的接口 - Python/jQuery库,使AJAX易于在Web应用程序中使用
每种类型的扩展通常提供有关其用法的大量文档。由于扩展是一个Python模块,因此需要导入它才能使用它。
Flask 邮件
基于web的应用程序通常需要具有向用户发送邮件的功能。Flask-Mail扩展使得与任何电子邮件服务器建立简单的接口变得非常容易。
首先,应该在pip下安装Flask-Mail扩展。
pip install Flask-Mail
其使用可以分为以下几步
-
配置Flask-Mail的配置项
-
创建邮递系统对象
-
创建邮件对象
-
使用邮递系统对象发送消息
Flask-Mail的配置项
序号 | 参数与描述 |
---|---|
1 | MAIL_SERVER 电子邮件服务器的名称/IP地址 |
2 | MAIL_PORT 使用的服务器的端口号 |
3 | MAIL_USE_TLS 启用/禁用传输安全层加密 |
4 | MAIL_USE_SSL 启用/禁用安全套接字层加密 |
5 | MAIL_DEBUG 调试支持。默认值是Flask应用程序的调试状态 |
6 | MAIL_USERNAME 发件人的用户名 |
7 | MAIL_PASSWORD 发件人的密码 |
8 | MAIL_DEFAULT_SENDER 设置默认发件人 |
Mail类
用于构建邮递系统对象的类,它管理电子邮件消息传递需求,构造函数将Flask应用程序(app)对象作为参数。
flask-mail.Mail(app = None)
Mail类的方法
序号 | 方法与描述 |
---|---|
1 | send()发送消息对象 |
2 | connect()打开与邮件主机的连接 |
3 | send_message()发送消息对象 |
Message类
用于构建邮件对象的类,它封装了一封电子邮件的内容。Message类构造函数有几个参数:
flask-mail.Message(subject, recipients, body, html, sender, cc, bcc,
reply-to, date, charset, extra_headers, mail_options, rcpt_options)
Message类方法
attach() - 为邮件添加附件。此方法一般采用以下参数:
- filename - 要附加的文件的名称
- content_type - MIME类型的文件
- data - 原始文件数据
add_recipient() - 向邮件添加另一个收件人
关于使用Flask发送邮件的demo,可以参见 flask_mail发送邮件(附源码),里面有发送普通文本邮件、发送一个html模板的邮件、发送一个附带附件的邮件的代码示例,私以为写得还是挺全的。
Flask WTF
HTML提供了一个****标签,可以适当地使用Form(表单)元素,例如文本输入,单选按钮,选择等。
用户输入的数据以Http请求消息的形式通过GET或POST方法提交给服务器端脚本。
而使用HTML表单的一个缺点是很难动态呈现表单元素。HTML本身无法验证用户的输入。
而在Flask中,为了处理web表单,我们一般使用Flask-WTF扩展,它封装了WTForms(WTForms的作用,就是提供一个灵活的表单,能够方便使用。Flask-WTF扩展为这个WTForms库提供了一个简单的接口),使用Flask-WTF表单扩展,可以帮助进行CSRF验证,帮助我们快速定义表单字段并使用HTML模板进行渲染,而且可以将验证应用于WTF字段。
WTforms包中包含各种表单字段的定义。下面列出了一些标准表单字段。
序号 | 标准表单字段与描述 |
---|---|
1 | TextField 表示 HTML表单元素 |
2 | BooleanField 表示 HTML表单元素 |
3 | DecimalField 用于显示带小数的数字的文本字段 |
4 | IntegerField 用于显示整数的文本字段 |
5 | RadioField 表示 HTML表单元素 |
6 | SelectField 表示选择表单元素 |
7 | TextAreaField 表示 HTML表单元素 |
8 | PasswordField 表示 HTML表单元素 |
9 | SubmitField 表示表单元素 |
下面列出一些WTForms常用验证函数
序号 | 验证器类与描述 |
---|---|
1 | DataRequired 检查输入字段是否为空 |
2 | Email 检查字段中的文本是否遵循电子邮件ID约定 |
3 | IPAddress 在输入字段中验证IP地址 |
4 | Length 验证输入字段中的字符串的长度是否在给定范围内 |
5 | NumberRange 验证给定范围内输入字段中的数字 |
6 | URL验证在输入字段中输入的URL |
对于在Flask中使用WTF扩展创建表单类、使用模板渲染表单、获取表单数据,并对表单的数据进行校验,Flask:Flask-WTF扩展 一文在1.1—1.4中做了使用示例。
Flask SQLAlchemy
关于ORM
ORM全称Object Relation Mapping(对象关系映射),主要实现模型对象到关系数据库数据的映射,比如:把数据库表中每条记录映射为一个模型对象。
关于SQLAlchemy
SQLAlchemy是一个基于Python的ORM框架。该框架是建立在DB-API之上(DB-API是Python的数据库接口规范),使用对象关系映射进行数据库操作。
DB API的作用如下
关于SQLAlchemy的基本认识和使用,可戳 使用SQLAlchemy | 廖雪峰
进入正题:Flask SQLAlchemy
Flask-SQLAlchemy是Flask扩展,它将对SQLAlchemy的支持添加到Flask应用程序中。
我们一步步来简单列举Flask SQLAlchemy的用法
步骤2 - 安装Flask-SQLAlchemy扩展。
pip install flask-sqlalchemy
步骤2 - 您需要从此模块导入SQLAlchemy类。
from flask_sqlalchemy import SQLAlchemy
步骤3 - 现在创建一个Flask应用程序对象并为要使用的数据库设置URI。
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@127.0.0.1/flask_books'
步骤4 - 然后使用app对象作为参数创建SQLAlchemy类的对象。该对象包含用于ORM操作的辅助函数。它还提供了一个父Model类,要使用它来声明用户定义的数据模型。在下面的代码段中,创建了books模型。
db = SQLAlchemy(app)
class Books(db.Model):
# 表名
__tablename__ = "books"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(16), unique=True)
author_id = db.Column(db.Integer,db.ForeignKey("authors.id"))
def __repr__(self):
return "books:%s %s" % {self.name,self.author_id}
步骤5 - 要在数据库中创建所有定义好的数据表(上面定义好的books数据模型),请运行create_all()方法。
db.create_all()
SQLAlchemy的session对象管理ORM对象的所有持久性操作。
以下session方法执行CRUD操作(CRUD操作要db.session.commit()之后才开始真正执行):
-
db.session.add (模型对象) - 将记录插入到映射表中
-
db.session.delete (模型对象) - 从表中删除记录
-
model.query.all() - 从表中检索所有记录(对应于SELECT查询)。
还可以使用filter属性用于过滤返回检索得到的记录集。例如要在books表中检索name='东野圭吾’的记录:
Author.query.filter_by(name = "东野圭吾").first()
一个结合使用了Flask WTF和Flask SQLAlchemy的图书管理的demo,可以见我之前写的博客:小坨的Flask之图书管理小案例
一个Flask的综合案例:问答论坛
此小demo是基于Flask和MySQL搭建起来的问答平台,是我在学习过程中按b站:Python Flask零基础到项目实战系列-项目实战 手敲起来的一个小demo,它综合涵盖了上面讲到的Flask知识点。
代码在我的GitHub上:https://github.com/atuo-200/flask_questions-and-answers_demo