avatar

Flask学习教程一——基础

本文主要参考https://www.w3cschool.cn/flask/Flask-3ask1yho.html
本文大致按照参考资料架构书写,对代码错误或版本不兼容进行了修正
如果需要更严谨的教程请参考官方文档

  • 本文由于python2和python3共存,且使用python3环境运行,用pip3代替pip
  • windows10
  • Pycharm专业版和Jupyter Notebook
  • Python 3.7.2
    Flask 1.1.1
    Werkzeug 0.16.0
  • 要求有python和html基础

Flask 概述

什么是Web Framework?

Web Application Framework(Web应用程序框架)或简单的Web Framework(Web框架)表示一个库和模块的集合,使Web应用程序开发人员能够编写应用程序,而不必担心协议,线程管理等低级细节。

什么是Flask?

Flask是一个用Python编写的Web应用程序框架。 它由 Armin Ronacher 开发,他领导一个名为Pocco的国际Python爱好者团队。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目。

WSGI

Web Server Gateway Interface(Web服务器网关接口,WSGI)已被用作Python Web应用程序开发的标准。WSGI是Web服务器和Web应用程序之间通用接口的规范。

Werkzeug

它是一个WSGI工具包,它实现了请求,响应对象和实用函数。 这使得能够在其上构建web框架。 Flask框架使用Werkzeug作为其基础之一。

jinja2

jinja2是Python的一个流行的模板引擎。Web模板系统将模板与特定数据源组合以呈现动态网页。

Flask通常被称为微框架。 它旨在保持应用程序的核心简单且可扩展。Flask没有用于数据库处理的内置抽象层,也没有形成验证支持。相反,Flask支持扩展以向应用程序添加此类功能。一些受欢迎的Flask扩展将在本教程后续章节进行讨论。

环境搭建

virtualenv

pip3 install virutalenv
mkdir newproj
cd newproj
virtualenv venv
venv\scripts\activate

或者在新建项目时在“环境中”选择virtualenv

Flask

pip3 install Flask
  • 注:pycharm专业版对flask有特殊支持,博主使用的是学生账号

    img

Flask应用

Hello world

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
return 'Hello World'

if __name__ == '__main__':
app.run()

函数解释

app = Flask(_name_)

Flask构造函数使用当前模块(__name __)的名称作为参数。

app.run()

Flask类的run()方法在本地开发服务器上运行应用程序。

app.run(host, port, debug, options)

所有参数都是可选的

序号 参数与描述
1 host 要监听的主机名。 默认为127.0.0.1(localhost)。设置为“0.0.0.0”以使服务器在外部可用
2 port 默认值为5000
3 debug 默认为false。 如果设置为true,则提供调试信息
4 options 要转发到底层的Werkzeug服务器。

调试模式

通过调用run()方法启动Flask应用程序。但是,当应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。为避免这种不便,请启用调试支持。如果代码更改,服务器将自行重新加载。它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有的话)。

在运行或将调试参数传递给run()方法之前,通过将application对象的debug属性设置为True来启用Debug模式。

app.debug = True
app.run()
app.run(debug = True)

Flask路由

Flask中的route()装饰器用于将URL绑定到函数。

app.route(rule, options)
  • rule 参数表示与该函数的URL绑定。
  • options 是要转发给基础Rule对象的参数列表。

    @app.route(‘/‘)

    @app.route('/')
    def hello_world():
    return 'hello world'
    在上面的示例中,’/ ‘ URL与hello_world()函数绑定。因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。

@app.route(‘/hello’)

@app.route('/hello')
def hello_world():
return 'hello world'

访问http:// localhost:5000/hello URL,hello_world()函数的输出将在浏览器中呈现。
此时localhost:5000将返回404

Flask变量规则

构建动态URL,变量部分标记为<variable-name>。它作为关键字参数传递给与规则相关联的函数。

from flask import Flask
app = Flask(__name__)

if __name__ == '__main__':
app.run(debug = True)

如果

序号 转换器和描述
0 接受字符串 %s
1 int接受整数 %d
2 float对于浮点值 %f
3 *path *接受用作目录分隔符的斜杠

在下面的代码中,使用了所有这些构造函数:

from flask import Flask
app = Flask(__name__)

@app.route('/hello/<name>')
def hello_name(name):
return 'Hello %s!' % name
# 或者写为 return '<h1>hello {}</h1>'.format(name)

@app.route('/blog/<int:postID>')
def show_blog(postID):
return 'Blog Number %d' % postID

@app.route('/rev/<float:revNo>')
def revision(revNo):
return 'Revision Number %f' % revNo

if __name__ == '__main__':
app.run()

在浏览器中输入http://localhost:5000/hello/w3cschool作为URL , 则‘w3cschool’将作为参数提供给hello()函数。该页面讲显示Hello w3cschool!

访问浏览器中的URL http://localhost:5000/blog/11 。给定的数字用作show_blog()函数的参数。浏览器显示以下输出:

Blog Number 11

在浏览器中输入此URL - http://localhost:5000/rev/1.1

revision()函数将浮点数作为参数。以下结果显示在浏览器窗口中:

Revision Number 1.100000

定义规则

Flask的URL规则基于Werkzeug的路由模块。这确保形成的URL是唯一的,并且基于Apache规定的先例。

考虑以下脚本中定义的规则:

from flask import Flask
app = Flask(__name__)

@app.route('/flask')
def hello_flask():
return 'Hello Flask'

@app.route('/python/')
def hello_python():
return 'Hello Python'

if __name__ == '__main__':
app.run()

这两个规则看起来类似,但在第二个规则中,使用斜杠(/)。因此,它成为一个规范的URL。因此,使用/python/python/返回相同的输出。但是,如果是第一个规则,/flask/ URL会产生“404 Not Found”页面。

Flask 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)

如果访问/user/admin将调用hello_admin并跳转至/admin,如果访问的是/user/abc将调用hello_guest并跳转至/guest/abc

Flask HTTP方法

http方法 作用
GET 以未加密的形式将数据发送到服务器。最常见的方法。
POST 用于将HTML表单数据发送到服务器。POST方法接收的数据不由服务器缓存。

默认情况下,Flask路由响应GET请求,下面演示如何使用POST方法

login.html

<html>
<body>

<form action = "http://localhost:5000/login" method = "post">
<p>Enter Name:</p>
<p><input type = "text" name = "nm" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>

</body>
</html>
from flask import Flask, redirect, url_for, request
app = Flask(__name__)

@app.route('/success/<name>')
def success(name):
return 'welcome %s' % name

@app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
user = request.form['nm']
return redirect(url_for('success',name = user))
else:
user = request.args.get('nm')
return redirect(url_for('success',name = user))

if __name__ == '__main__':
app.run(debug = True)

在浏览器中以绝对路径打开login.html,输入Name

image-20200422231406177

点击submit,表单数据将POST到表单标签的action子句中的URL:http://localhost:5000/login映射到login()函数。由于服务器通过POST方法接收数据,因此通过以下步骤获得从表单数据获得的“nm”参数的值:

user = request.form['nm']

它作为变量部分传递给‘/ success’ URL。浏览器在窗口中显示welcome消息。

image-20200422231453521

login.html中将方法参数更改为‘GET’,然后在浏览器中再次打开它。服务器上接收的数据是通过GET方法获得的。通过以下的步骤获得’nm’参数的值:

user = request.args.get(‘nm’)

这里,args是包含表单参数对及其对应值对的列表的字典对象。与’nm’参数对应的值将像之前一样传递到/success

Flask模板

介绍

web模板系统:设计html,可以动态插入数据

转义符

Jinja2模板引擎使用以下分隔符从HTML转义。

{% ... %}用于语句
{{ ... }}用于表达式可以打印到模板输出
{# ... #}用于未包含在模板输出中的注释
\# ... ##用于行语句
{% endnote %}

样例1——占位符

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def index():
return render_template('hello.html')


@app.route('/hello/<user>')
def hello_name(user):
return render_template('hello.html', name=user)


if __name__ == '__main__':
app.debug=True
app.run()

在templates文件夹中创建hello.html:

<!doctype html>
<h1>Hello {{ name }}!</h1>
image-20200423000839414

URL的变量部分插入占位符。image-20200423000811200

样例2——条件语句

@app.route('/hello/<int:score>')
def hello_name(score):
return render_template('hello.html', marks = score)
<!doctype html>
{% if marks>50 %}
<h1> Your result is pass!</h1>
{% else %}
<h1>Your result is fail</h1>
{% endif %}

image-20200423001839968image-20200423001901327

样例三——表格

@app.route('/')
def result():
dict = {'phy':50,'che':60,'maths':70}
return render_template('result.html', result = dict)
<table border="8">
{% for key, value in result.items() %}
<tr>
<th>{{ key }} </th>
<td>{{ value }} </td>
</tr>
{% endfor %}
</table>
image-20200423115824810
  • 注:参考资料里的<tr>使用了转义字符,不要直接复制

Flask静态文件

特殊端点’static’用于生成静态文件的URL。

/app.py

@app.route("/")
def index():
return render_template("hello.html")

/templates/hello.html

<html>
<head>
<script type = "text/javascript"
src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
</head>
<body>
<input type = "button" onclick = "sayHello()" value = "Say Hello" />
</body>
</html>

/static/hello.js

function sayHello() {
alert("Hello World")
}

hello.html中的HTML按钮的OnClick事件上调用hello.js中定义的javascript函数,该函数在Flask应用程序的“/”URL上呈现。

image-20200423121323813

点击按钮后:

image-20200423121351647

Flask Request对象

来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。

Request对象的重要属性如下所列:

  • Form - 它是一个字典对象,包含表单参数及其值的键和值对。
  • args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
  • Cookies - 保存Cookie名称和值的字典对象。
  • files - 与上传文件有关的数据。
  • method - 当前请求方法。

Flask 将表单数据发送到模板

在以下示例中,‘/‘ URL会呈现具有表单的网页(student.html)。填入的数据会发布到触发 result()函数的‘/result’ URL

results()函数收集字典对象中的request.form中存在的表单数据,并将其发送给result.html

该模板动态呈现表单数据的HTML表格。

from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def student():
return render_template('student.html')

@app.route('/result',methods = ['POST', 'GET'])
def result():
if request.method == 'POST':
result = request.form
return render_template("result.html",result = result)


if __name__ == '__main__':
app.run(debug=True)

student.html

<form action = "http://localhost:5000/result" method = "POST" >
<p>Name <input type = "text" name = "Name" /></p>
<p>Physics <input type = "text" name = "Physics" /></p>
<p>Chemistry <input type = "text" name = "chemistry" /></p>
<p>Maths <input type ="text" name = "Mathematics" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>

result.html

<!doctype html>
<html>
<body>
<table border = 1>
{% for key, value in result.items() %}
<tr>
<th> {{ key }} </th>
<td> {{ value }} </td>
</tr>
{% endfor %}
</table>
</body>
</html>

image-20200423133927822image-20200423133942432

当点击提交按钮时,表单数据以HTML表格的形式呈现在result.htmlimage-20200423134025212

Flask Cookies

Cookie以文本文件的形式存储在客户端的计算机上,其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。

Request对象包含Cookie的属性。它是所有cookie变量及其对应值的字典对象,客户端已传输。除此之外,cookie还存储其网站的到期时间,路径和域名。

在Flask中,对响应对象设置cookie。使用make_response()函数从视图函数的返回值获取响应对象。之后,使用响应对象的set_cookie()函数来存储cookie。

读回cookie很容易。request.cookies属性的get()方法用于读取cookie。

make_response()

该点转载自:https://www.jianshu.com/p/44d88abb9515

make_response(),相当于DJango中的HttpResponse。

from flask import Flask,make_response,render_template
app = Flask(__name__)

# 1.返回内容
@app.route('/')
def make_response_function():
response = make_response('<h2>羞羞哒</h2>')
return response, 404

# 2.返回页面
@app.route('/makeresponse/')
def make_response_function():
return render_template('hello.html')

注意:make_response 想要返回页面,不能直接写做:make_response(‘hello.html’),必须用render_template(‘hello.html’)形式。

样例一

# 转载自:https://blog.csdn.net/wei18791957243/article/details/85172653
from flask import Flask, make_response, request

app = Flask(__name__)


@app.route("/set_cookie")
def set_cookie():
resp = make_response("success")
'''
设置cookie,默认有效期是临时cookie,浏览器关闭就失效
可以通过 max_age 设置有效期, 单位是秒
'''''
resp.set_cookie("Itcast_1", "python_1")
resp.set_cookie("Itcast_2", "python_2")
resp.set_cookie("Itcast_3", "python_3", max_age=3600)
return resp


@app.route("/get_cookie")
def get_cookie():
"""
获取cookie,通过reques.cookies的方式,
返回的是一个字典,可以用get的方式
"""
cookie_1 = request.cookies.get("Itcast_1") # 获取名字为Itcast_1对应cookie的值
return cookie_1


@app.route("/delete_cookie")
def delete_cookie():
"""
删除cookie,通过delete_cookie()的方式,
里面是cookie的名字
这里的删除只是让cookie过期,并不是直接删除cookie
"""
resp = make_response("del success")
resp.delete_cookie("Itcast1")
return resp


if __name__ == '__main__':
app.run(debug=True)

样例二

参考:https://blog.csdn.net/weixin_41287692/article/details/88951735

from flask import Flask, make_response, request,render_template

app = Flask(__name__)


@app.route('/')
def index():
return render_template('index.html')


@app.route('/setcookie', methods=['POST', 'GET'])
def setcookie():
if request.method == 'POST':
user = request.form['nm']
resp = make_response(render_template('readcookie.html'))
resp.set_cookie('userID', user)
return resp


@app.route('/getcookie')
def getcookie():
name = request.cookies.get('userID')
return '<h1>welcome '+name+'</h1>'

if __name__ == '__main__':
app.run(debug=True)

readcookie.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="/getcookie">getcookie</a>
</body>
</html>

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>
image-20200423151849332 image-20200423151859486 image-20200423151907928

Flask 会话

与Cookie不同,Session(会话)数据存储在服务器上。会话是客户端登录到服务器并注销服务器的时间间隔。需要在该会话中保存的数据会存储在服务器上的临时目录中。

为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的SECRET_KEY

Session对象也是一个字典对象,包含会话变量和关联值的键值对。

以下内容参考:https://www.jianshu.com/p/dd0aa75f3f0e

flask中如何操作session

from flask import Flask,session
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
# 添加数据到session中
# 操作session的时候 跟操作字典是一样的。
# SECRET_KEY

@app.route('/')
def hello_world():
session['username'] = 'zhangsan'
return 'Hello World!'

if __name__ == '__main__':
app.run(debug=True)

在python中操作session的方式和操作字典的方式非常类似,session['username'] = 'zhangsan' 就是给session中的变量username赋值。在flask中操作session有一点需要注意,就是需要设置一个’SECRET_KEY’。可以单独在配置文件中写SECRET_KEY。

SECRET_KEY = 'abc'

或者直接写

app.config['SECRET_KEY'] = 'abc'

都是可以的,我这里用了一个随机的变量,而且是24位的。 os.urandom(24) 会从 0-9,a-z A-Z中随机选中24个字符串用做加密session的秘钥。或者称之为 “盐”。设置好之后执行下代码,然后在谷歌浏览器中找找这个session。在谷歌浏览器中找到设置,然后在最下面找到高级
找到内容设置。找到Cookie
然后找到查看所有Cookie和网站数据 搜索127.0.0.1
到这个里就可以看到咱们添加的session值了,但是这个内容是加密后的。

image-20200423200644076

获取session值

@app.route('/get/')
def get():
# session['username'] 如果username不存在则会抛出异常
# session.get('username') 如果username不存在会得到 none 不会报错 推荐使用
return session.get('username')

这里咱们获取值一般是用session.get('username')这样即使session值不存在也不会抛出异常。

image-20200423205217176

删除清空session

@app.route('/delete/')
def delete():
print(session.get('username'))
session.pop('username')
print(session.get('username'))
return 'success'

@app.route('/clear/')
def clear():
print(session.get('username'))
# 删除session中的所有数据
session.clear()
print(session.get('username'))
return 'success'

设置session的过期时间

一般session都是有一个过期时间的,

如果没有指定session的过期时间,那么默认是浏览器关闭就自动结束,
如果设置了session的permanent属性为True,那么过期时间是31天。

默认image-20200423205342123

设置session的过期时间:

from datetime import timedelta
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
session.permanent = True

当只设置了session.permanent = True时,可以看到浏览器中127.0.0.1中的session过期时间为31天。

image-20200423205539390 当设置 `app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)`时,可以看到session的过期时间变成7天了。 image-20200423205547594

完整代码

from flask import Flask,session
import os
from datetime import timedelta
app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
# 添加数据到session中
# 操作session的时候 跟操作字典是一样的。
# SECRET_KEY

@app.route('/')
def hello_world():
session['username'] = 'zhangsan'
# 如果没有指定session的过期时间,那么默认是浏览器关闭就自动结束
# 如果设置了session的permanent属性为True,那么过期时间是31天。
session.permanent = True
return 'Hello World!'

@app.route('/get/')
def get():
# session['username'] 如果username不存在则会抛出异常
# session.get('username') 如果username不存在会得到 none 不会报错 推荐使用
return session.get('username')

@app.route('/delete/')
def delete():
print(session.get('username'))
session.pop('username')
print(session.get('username'))
return 'success'

@app.route('/clear/')
def clear():
print(session.get('username'))
# 删除session中的所有数据
session.clear()
print(session.get('username'))
return 'success'

if __name__ == '__main__':
app.run(debug=True)

Flask 重定向和错误

redirect()函数

Flask类有一个redirect()函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。

redirect()函数的原型如下:

Flask.redirect(location, statuscode, response)

在上述函数中:

  • location参数是应该重定向响应的URL。
  • statuscode发送到浏览器标头,默认为302。
  • response参数用于实例化响应。

状态码

以下状态代码已标准化:

  • HTTP_300_MULTIPLE_CHOICES
  • HTTP_301_MOVED_PERMANENTLY
  • HTTP_302_FOUND
  • HTTP_303_SEE_OTHER
  • HTTP_304_NOT_MODIFIED
  • HTTP_305_USE_PROXY
  • HTTP_306_RESERVED
  • HTTP_307_TEMPORARY_REDIRECT

默认状态代码为302,表示‘found’

样例一

在以下示例中,redirect()函数用于在登录尝试失败时再次显示登录页面。

from flask import Flask, redirect, url_for, render_template, request
# Initialize the Flask application
app = Flask(__name__)

@app.route('/')
def index():
return render_template('login.html')

@app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST' and
request.form['username'] == 'admin' :
return redirect(url_for('success'))
return redirect(url_for('index'))

@app.route('/success')
def success():
return 'logged in successfully'

if __name__ == '__main__':
app.run(debug = True)

abort()函数

Flask类具有带有错误代码的abort()函数。

Flask.abort(code)

Code参数采用以下值之一:

  • 400 - 用于错误请求
  • 401 - 用于未身份验证的
  • 403 - Forbidden
  • 404 - 未不到
  • 406 - 表示不接受
  • 415 - 用于不支持的媒体类型
  • 429 - 请求过多

样例二

让我们对上述代码中的login()函数稍作更改。如果要显示‘Unauthurized’页面,请将其替换为调用abort(401),而不是重新显示登录页面。

from flask import Flask, redirect, url_for, render_template, request, abort
app = Flask(__name__)

@app.route('/')
def index():
return render_template('login.html')

@app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
if request.form['username'] == 'admin' :
return redirect(url_for('success'))
else:
abort(401)
else:
return redirect(url_for('index'))

@app.route('/success')
def success():
return 'logged in successfully'

if __name__ == '__main__':
app.run(debug = True)

演示

login.html

注意表明post

<form action = "http://localhost:5000/login" method = "post">
<p><input type = 'text' name = username></p>
<p><input type = 'submit' value = Login></p>
</form>
结果
  • 输入admin image-20200424113759201

  • 输入其它内容,触发abort(401)

image-20200424113704823

image-20200424113725315

Flask 消息闪现

一个好的基于GUI的应用程序会向用户提供有关交互的反馈。例如,桌面应用程序使用对话框或消息框,JavaScript使用警报用于类似目的。

在Flask Web应用程序中生成这样的信息性消息很容易。Flask框架的闪现系统可以在一个视图中创建消息,并在名为next的视图函数中呈现它。

Flask模块包含flash()方法。它将消息传递给下一个请求,该请求通常是一个模板。

flash(message, category)

其中,

  • message参数是要闪现的实际消息。
  • category参数是可选的。它可以是“error”,“info”或“warning”。

为了从会话中删除消息,模板调用get_flashed_messages()

get_flashed_messages(with_categories, category_filter)

两个参数都是可选的。如果接收到的消息具有类别,则第一个参数是元组。第二个参数仅用于显示特定消息。

以下闪现在模板中接收消息。

{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}

样例

app.py

from flask import Flask, redirect, url_for, render_template, request, flash
import os

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(24)


@app.route('/')
def index():
return render_template('index.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
error = None

if request.method == 'POST':
if request.form['username'] != 'admin' or \
request.form['password'] != 'admin':
error = 'Invalid username or password. Please try again!'
else:
flash('You were successfully logged in')
return redirect(url_for('index'))

return render_template('login.html', error=error)


if __name__ == '__main__':
app.run(debug=True)

login.html

<!doctype html>
<h1>Login</h1>
{% if error %}
<p><strong>Error:</strong> {{ error }}
{% endif %}

<form action = "http://localhost:5000/login" method = "post">
<dl>
<dt>Username:</dt>
<dd><input type = text name="username" value="{{ request.form.username }}"></dd>
<dt>Pssword:</dt>
<dd><input type="password" name="password"></dd>
</dl>
<p><input type="submit" value="Login"></p>
</form>

index.html

<!doctype html>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}

<h1>Flask Message Flashing Example</h1>
<p>Do you want to <a href = "{{ url_for('login') }}">
<b>log in?</b></a></p>
image-20200424134357446 image-20200424134512696 image-20200424134521156 image-20200424134528432 image-20200424134535905

Flask 文件上传

在Flask中处理文件上传非常简单。它需要一个HTML表单,其enctype属性设置为“multipart / form-data”,将文件发布到URL。URL处理程序从request.files[]对象中提取文件,并将其保存到所需的位置。

每个上传的文件首先会保存在服务器上的临时位置,然后将其实际保存到它的最终位置。目标文件的名称可以是硬编码的,也可以从request.files[file]对象的filename属性中获取。但是,建议使用secure_filename()函数获取它的安全版本。

可以在Flask对象的配置设置中定义默认上传文件夹的路径和上传文件的最大大小。

app.config[‘UPLOAD_FOLDER’] 定义上传文件夹的路径
app.config[‘MAX_CONTENT_PATH’] 指定要上传的文件的最大大小(以字节为单位)

以下代码具有’/ upload’ URL规则,该规则在templates文件夹中显示’upload.html’,以及‘/ upload-file’ URL规则,用于调用uploader()函数处理上传过程。

‘upload.html’有一个文件选择器按钮和一个提交按钮。

<html>
<body>

<form action = "http://localhost:5000/uploader" method = "POST"
enctype = "multipart/form-data">
<input type = "file" name = "file" />
<input type = "submit"/>
</form>

</body>
</html>

您将看到如下所示的界面。

image-20200424135529049 image-20200424135612781

选择文件后,单击提交。表单的post方法调用‘/ upload_file’ URL。底层函数uploader()执行保存操作。

image-20200424135621372

以下是Flask应用程序的Python代码。

from flask import Flask, render_template, request
from werkzeug import secure_filename
app = Flask(__name__)

@app.route('/')
def upload_file():
return render_template('upload.html')

@app.route('/uploader', methods = ['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['file'] # URL处理程序从request.files[]对象中提取文件,并将其保存到所需的位置。
f.save(secure_filename(f.filename)) # 获取目标文件的名称
return 'file uploaded successfully'

if __name__ == '__main__':
app.run(debug = True)

Flask扩展

Flask通常被称为微框架,因为核心功能包括基于Werkzeug的WSGI和路由以及基于Jinja2的模板引擎。此外,Flask框架还支持cookie和会话,以及JSON,静态文件等Web帮助程序。显然,这不足以开发完整的Web应用程序。而Flask扩展就具备这样的功能Flask扩展为Flask框架提供了可扩展性。

有大量的Flask扩展可用。Flask扩展是一个Python模块,它向Flask应用程序添加了特定类型的支持。Flask Extension Registry(Flask扩展注册表)是一个可用的扩展目录。可以通过pip实用程序下载所需的扩展名。

在本教程中,我们将讨论以下重要的Flask扩展:

  • Flask Mail - 为Flask应用程序提供SMTP接口
  • Flask WTF - 添加WTForms的渲染和验证
  • Flask SQLAlchemy - 为Flask应用程序添加SQLAlchemy支持
  • Flask Sijax - Sijax的接口 - Python/jQuery库,使AJAX易于在Web应用程序中使用

每种类型的扩展通常提供有关其用法的大量文档。由于扩展是一个Python模块,因此需要导入它才能使用它。Flask扩展名通常命名为flask-foo。导入的操作如下:

from flask_foo import [class, function]

对于0.7以后的Flask版本,您还可以使用语法:

from flask.ext import foo

对于此用法,需要激活兼容性模块。它可以通过运行flaskext_compat.py来安装:

import flaskext_compat
flaskext_compat.activate()
from flask.ext import foo

Flask 邮件

基于web的应用程序通常需要具有向用户/客户端发送邮件的功能。Flask-Mail扩展使得与任何电子邮件服务器建立简单的接口变得非常容易。

首先,应该在pip实用程序的帮助下安装Flask-Mail扩展。

pip3 install 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设置默认发件人
9 MAIL_MAX_EMAILS设置要发送的最大邮件数
10 MAIL_SUPPRESS_SEND如果app.testing设置为true,则发送被抑制
11 MAIL_ASCII_ATTACHMENTS如果设置为true,则附加的文件名将转换为ASCII

flask-mail模块包含以下重要类的定义。

Mail类

它管理电子邮件消息传递需求。类构造函数采用以下形式:

flask-mail.Mail(app = None)

构造函数将Flask应用程序对象作为参数。

Mail类的方法

序号 方法与描述
1 send()发送Message类对象的内容
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() - 向邮件添加另一个收件人

from flask import Flask
# 步骤一:在代码中从flask-mail模块导入Mail和Message类。
from flask_mail import Mail, Message

app =Flask(__name__)

# 步骤二:然后按照以下设置配置Flask-Mail
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****' # 发件放邮箱需要开启POP3/SMTP服务,获取客户端授权码,填入app.config['MAIL_PASSWORD']
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
# 步骤三:创建Mail类的实例
mail = Mail(app)
# 步骤四:在由URL规则(‘/’)映射的Python函数中设置Message对象。
@app.route("/")
def index():
msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
msg.body = "Hello Flask message sent from Flask-Mail"
mail.send(msg)
return "Sent"

if __name__ == '__main__':
app.run(debug = True)

在发送至163邮箱时出现了被当成垃圾邮件被拒收的情况(TAT),发送到qq邮箱是可以的

Author: Michelle19l
Link: https://gitee.com/michelle19l/michelle19l/2020/04/22/Flask学习教程/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信
  • 支付寶
    支付寶