Flask - 快速指南
Flask – Overview
什么是Web框架?
Web应用程序框架或简单的Web框架代表了一组库和模块,使Web应用程序开发人员可以编写应用程序,而无需担心协议,线程管理等低级细节。
什么是Flask?
Flask是一个用Python编写的Web应用程序框架。 它由Armin Ronacher开发,他领导着一个名为Pocco的Python爱好者国际组织。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。 两者都是Pocco项目。
WSGI
Web服务器网关接口(WSGI)已被用作Python Web应用程序开发的标准。 WSGI是Web服务器和Web应用程序之间通用接口的规范。
Werkzeug
它是一个WSGI工具包,它实现了请求,响应对象和其他实用程序功能。 这使得能够在其上构建Web框架。 Flask框架使用Werkzeug作为其基础之一。
jinja2
jinja2是Python的流行模板引擎。 Web模板系统将模板与特定数据源组合以呈现动态网页。
Flask通常被称为微框架。 它旨在保持应用程序的核心简单而可扩展。 Flask没有用于数据库处理的内置抽象层,也没有形成验证支持。 相反,Flask支持扩展以向应用程序添加此类功能。 一些流行的Flask扩展将在本教程后面讨论。
Flask – Environment
先决条件(Prerequisite)
安装Flask通常需要Python 2.6或更高版本。 尽管Flask及其依赖项与Python 3(Python 3.3以上版本)配合良好,但许多Flask扩展都不能正确支持它。 因此,建议在Python 2.7上安装Flask。
为开发环境安装virtualenv
virtualenv是一个虚拟的Python环境构建器。 它可以帮助用户并排创建多个Python环境。 因此,它可以避免不同版本的库之间的兼容性问题。
以下命令安装virtualenv 。
pip install virtualenv
此命令需要管理员权限。 在Linux/Mac OS上的pip之前添加sudo 。 如果您使用的是Windows,请以管理员身份登录。 在Ubuntu上, virtualenv可以使用它的包管理器安装。
Sudo apt-get install virtualenv
安装后,将在文件夹中创建新的虚拟环境。
mkdir newproj
cd newproj
virtualenv venv
要激活相应的环境,请在Linux/OS X使用以下命令 -
venv/bin/activate
在Windows ,可以使用以下代码 -
venv\scripts\activate
我们现在准备在这种环境中安装Flask。
pip install Flask
上述命令可以直接运行,无需虚拟环境即可进行系统范围的安装。
Flask – Application
要测试Flask安装,请在编辑器Hello.py以下代码键入Hello.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello World’
if __name__ == '__main__':
app.run()
必须在项目中导入Flask模块。 Flask类的一个对象是我们的WSGI应用程序。
Flask构造函数将current module (__name__)的名称作为参数。
Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。
app.route(rule, options)
rule参数表示与该函数的URL绑定。
options是要转发到基础Rule对象的参数列表。
在上面的例子中, '/' URL与hello_world()函数绑定。 因此,当在浏览器中打开Web服务器的主页时,将呈现此功能的输出。
最后,Flask类的run()方法在本地开发服务器上运行应用程序。
app.run(host, port, debug, options)
所有参数都是可选的
Sr.No | 参数和描述 |
---|---|
1 | host 要收听的主机名。 默认为127.0.0.1(localhost)。 设置为“0.0.0.0”以使服务器在外部可用 |
2 | port 默认为5000 |
3 | debug 默认为false。 如果设置为true,则提供调试信息 |
4 | options 要转发到底层的Werkzeug服务器。 |
上面给出的Python脚本是从Python shell执行的。
Python Hello.py
Python shell中的消息通知您
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
在浏览器中打开上面的URL (localhost:5000) 。 将显示'Hello World'消息。
调试模式
通过调用run()方法启动Flask应用程序。 但是,在应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。 为避免这种不便,请启用debug support 。 如果代码更改,服务器将自行重新加载。 它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有的话)。
在运行或将调试参数传递给run()方法之前,通过将application对象的debug属性设置为True来启用Debug模式。
app.debug = True
app.run()
app.run(debug = True)
Flask – Routing
现代Web框架使用路由技术来帮助用户记住应用程序URL。 直接访问所需页面非常有用,无需从主页导航。
Flask中的route()装饰器用于将URL绑定到函数。 例如 -
@app.route(‘/hello’)
def hello_world():
return ‘hello world’
这里,URL '/hello'规则绑定到hello_world()函数。 因此,如果用户访问http://localhost:5000/hello URL,则hello_world()函数的输出将在浏览器中呈现。
应用程序对象的add_url_rule()函数也可用于将URL与函数绑定,如上例所示,使用route() 。
装饰者的目的也由以下表示 -
def hello_world():
return ‘hello world’
app.add_url_rule(‘/’, ‘hello’, hello_world)
Flask – Variable Rules
通过向规则参数添加可变部分,可以动态构建URL。 此变量部分标记为《variable-name》 。 它作为关键字参数传递给与规则关联的函数。
在以下示例中, route()装饰器的rule参数包含附加到URL '/hello' 《name》变量部分。 因此,如果在浏览器中输入http://localhost:5000/hello/IoWiki作为URL ,则'TutorialPoint'将作为参数提供给hello()函数。
from flask import Flask
app = Flask(__name__)
@app.route('/hello/<name>')
def hello_name(name):
return 'Hello %s!' % name
if __name__ == '__main__':
app.run(debug = True)
将上面的脚本保存为hello.py并从Python shell运行它。 接下来,打开浏览器并输入URL http://localhost:5000/hello/IoWiki.
以下输出将显示在浏览器中。
Hello IoWiki!
除了默认的字符串变量部分,还可以使用以下转换器构建规则 -
Sr.No | 转换器和描述 |
---|---|
1 | int 接受整数 |
2 | float 对于浮点值 |
3 | path 接受用作目录分隔符的斜杠 |
在以下代码中,使用了所有这些构造函数。
from flask import Flask
app = Flask(__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()
从Python Shell运行上面的代码。 访问浏览器中的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’s路由模块。 这可确保形成的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 Building
url_for()函数对于动态构建特定函数的URL非常有用。 该函数接受函数的名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于URL的变量部分。
以下脚本演示了url_for()函数的用法。
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(name) ,它接受来自URL的参数值。
User()函数检查收到的参数是否与'admin'匹配。 如果匹配,则使用url_for()将应用程序重定向到hello_admin()函数,否则将hello_guest()函数作为guest参数传递给hello_guest()函数。
保存上面的代码并从Python shell运行。
打开浏览器并输入URL作为 - http://localhost:5000/user/admin
浏览器中的应用程序响应是 -
Hello Admin
在浏览器中输入以下URL - http://localhost:5000/user/mvl
应用程序响应现在更改为 -
Hello mvl as Guest
Flask – HTTP methods
Http协议是万维网数据通信的基础。 在该协议中定义了从指定URL检索数据的不同方法。
下表总结了不同的http方法 -
Sr.No | 方法和描述 |
---|---|
1 | GET 以未加密的形式将数据发送到服务器。 最常见的方法。 |
2 | HEAD 与GET相同,但没有响应体 |
3 | POST 用于将HTML表单数据发送到服务器。 POST方法接收的数据不会被服务器缓存。 |
4 | PUT 用上传的内容替换目标资源的所有当前表示。 |
5 | DELETE 删除URL给出的目标资源的所有当前表示 |
默认情况下,Flask路由响应GET请求。 但是,可以通过为route()装饰器提供方法参数来更改此首选项。
为了演示在URL路由中使用POST方法,首先让我们创建一个HTML表单并使用POST方法将表单数据发送到URL。
将以下脚本另存为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>
现在在Python shell中输入以下脚本。
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,然后单击Submit 。
表单数据将POST到表单标记的action子句中的URL。
http://localhost/login映射到login()函数。 由于服务器通过POST方法接收数据,因此从表格数据获得的'nm'参数值是通过 - 获得的 -
user = request.form['nm']
它作为可变部分传递给'/success' 。 浏览器在窗口中显示welcome消息。
在login.html中将方法参数更改为'GET' ,然后在浏览器中再次打开它。 服务器上收到的数据是通过GET方法获得的。 'nm'参数的值现在由 - 获得 -
User = request.args.get(‘nm’)
这里, args是包含表单参数对及其对应值的列表的字典对象。 与'nm'参数对应的值将像以前一样传递到'/ success'URL。
Flask – Templates
可以以HTML的形式返回绑定到某个URL的函数的输出。 例如,在以下脚本中, hello()函数将呈现附加了《h1》标记的'Hello World' 。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<html><body><h1>'Hello World'</h1></body></html>'
if __name__ == '__main__':
app.run(debug = True)
但是,从Python代码生成HTML内容非常麻烦,尤其是在需要放置变量数据和Python语言元素(如条件或循环)时。 这需要经常从HTML中转义。
这是人们可以利用Flask所基于的Jinja2模板引擎的地方。 而不是从函数返回硬编码HTML,可以通过render_template()函数呈现HTML文件。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return render_template(‘hello.html’)
if __name__ == '__main__':
app.run(debug = True)
Flask将尝试在模板文件夹中找到HTML文件,该文件存在于此脚本所在的文件夹中。
- 应用文件夹
- Hello.py
- templates
- hello.html
术语'web templating system'指的是设计HTML脚本,其中可以动态插入可变数据。 Web模板系统包括模板引擎,某种数据源和模板处理器。
Flask使用jinja2模板引擎。 Web模板包含用于变量和表达式(在这些情况下为Python表达式)的HTML语法散布占位符,这些是在呈现模板时替换的值。
以下代码在templates文件夹中保存为hello.html 。
<!doctype html>
<html>
<body>
<h1>Hello {{ name }}!</h1>
</body>
</html>
接下来,从Python shell运行以下脚本。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<user>')
def hello_name(user):
return render_template('hello.html', name = user)
if __name__ == '__main__':
app.run(debug = True)
当开发服务器开始运行时,打开浏览器并输入URL作为 - http://localhost:5000/user/mvl
URL的variable部分插入{{ name }}占位符。
jinja2模板引擎使用以下分隔符从HTML转义。
- {%...%}用于语句
- {{...}}表达式可以打印到模板输出
- {#...#}用于注释未包含在模板输出中
- #... ##用于行语句
在以下示例中,演示了在模板中使用条件语句。 hello()函数的URL规则接受整数参数。 它被传递给hello.html模板。 在其中,比较接收的数字(标记)的值(大于或小于50),因此有条件地呈现HTML。
Python脚本如下 -
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/hello/<int:score>')
def hello_name(score):
return render_template('hello.html', marks = score)
if __name__ == '__main__':
app.run(debug = True)
hello.html HTML模板脚本如下 -
<!doctype html>
<html>
<body>
{% if marks>50 %}
<h1> Your result is pass!</h1>
{% else %}
<h1>Your result is fail</h1>
{% endif %}
</body>
</html>
请注意,条件语句if-else和endif包含在分隔符{%..%} 。
运行Python脚本并访问URL http://localhost/hello/60 ,然后访问http://localhost/hello/30以查看HTML的输出是否有条件地更改。
Python循环结构也可以在模板中使用。 在以下脚本中,当在浏览器中打开URL http://localhost:5000/result时, result()函数将字典对象发送到模板results.html 。
result.html的Template部分使用for loop将字典对象result{}键和值对呈现为HTML表的单元格。
从Python shell运行以下代码。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/result')
def result():
dict = {'phy':50,'che':60,'maths':70}
return render_template('result.html', result = dict)
if __name__ == '__main__':
app.run(debug = True)
将以下HTML脚本保存为templates文件夹中的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>
这里,对应于For循环的Python语句再次包含在{%..%}中,而表达式key and value放在{{ }} 。
开发开始运行后,在浏览器中打开http://localhost:5000/result以获得以下输出。
Flask – Static Files
Web应用程序通常需要静态文件,例如javascript文件或支持网页显示的CSS文件。 通常,Web服务器配置为为您服务,但在开发过程中,这些文件是从包中的static文件夹或模块旁边提供的,它将在应用程序的/static提供。
特殊端点“static”用于生成静态文件的URL。
在下面的示例中,在index.html的HTML按钮的OnClick事件上调用hello.js定义的javascript函数,该函数在Flask应用程序的'/' URL上呈现。
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
if __name__ == '__main__':
app.run(debug = True)
index.html的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>
hello.js包含sayHello()函数。
function sayHello() {
alert("Hello World")
}
Flask – Request Object
来自客户端网页的数据作为全局请求对象发送到服务器。 为了处理请求数据,应该从Flask模块导入。
请求对象的重要属性如下所示 -
Form - 它是一个字典对象,包含表单参数及其值的键和值对。
args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
Cookies - 持有Cookie名称和值的字典对象。
files - 与上传文件有关的数据。
method - 当前请求方法。
Flask – Sending Form Data to Template
我们已经看到可以在URL规则中指定http方法。 触发函数接收的Form数据可以以字典对象的形式收集它并将其转发到模板以在相应的网页上呈现它。
在以下示例中, '/' URL呈现具有表单的网页(student.html)。 填充的数据将发布到'/result' result'URL,触发result()函数。
results()函数收集字典对象中request.form中存在的表单数据,并将其发送到result.html 。
该模板动态呈现form数据的HTML表格。
以下是Python的应用程序代码 -
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的HTML脚本。
<html>
<body>
<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>
</body>
</html>
模板代码(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>
运行Python脚本并在浏览器中输入URL http://localhost:5000/ 。
单击“ Submit按钮后,表单数据将以HTML表格的形式呈现在result.html上。
Flask – Cookies
Cookie以文本文件的形式存储在客户端的计算机上。 其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和站点统计信息。
Request object包含cookie的属性。 它是所有cookie变量及其对应值的字典对象,客户端已传输。 除此之外,cookie还存储其网站的到期时间,路径和域名。
在Flask中,cookie设置在响应对象上。 使用make_response()函数从视图函数的返回值中获取响应对象。 之后,使用响应对象的set_cookie()函数来存储cookie。
回读cookie很容易。 request.cookies属性的get()方法用于读取cookie。
在下面的Flask应用程序中,当您访问'/' URL时会打开一个简单的表单。
@app.route('/')
def index():
return render_template('index.html')
此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>
表格将发布到'/setcookie'网址。 关联的视图函数设置Cookie名称userID并呈现另一个页面。
@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
'readcookie.html'包含指向另一个视图函数getcookie()的超链接,该函数读取并在浏览器中显示cookie值。
@app.route('/getcookie')
def getcookie():
name = request.cookies.get('userID')
return '<h1>welcome '+name+'</h1>'
运行应用程序并访问http://localhost:5000/
设置cookie的结果显示如下 -
回读cookie的输出如下所示。
Flask – Sessions
与Cookie不同, Session数据存储在服务器上。 会话是客户端登录服务器并注销服务器的时间间隔。 需要在此会话中保存的数据存储在服务器上的临时目录中。
为每个客户端的Session ID分配Session ID 。 会话数据存储在cookie之上,服务器以加密方式对其进行签名。 对于此加密,Flask应用程序需要定义的SECRET_KEY 。
Session对象也是一个字典对象,包含会话变量和关联值的键值对。
例如,要设置'username'会话变量,请使用以下语句 -
Session[‘username’] = ’admin’
要释放会话变量,请使用pop()方法。
session.pop('username', None)
以下代码是Flask中会话工作的简单演示。 URL '/'只是提示用户登录,因为未设置会话变量'username' 。
@app.route('/')
def index():
if 'username' in session:
username = session['username']
return 'Logged in as ' + username + '<br>' + \
"<b><a href = '/logout'>click here to log out</a></b>"
return "You are not logged in <br><a href = '/login'></b>" + \
"click here to log in</b></a>"
当用户浏览“/ login”login()视图函数时,因为它是通过GET方法调用的,所以打开一个登录表单。
表单将回发到'/login' ,现在会话变量已设置。 应用程序重定向到'/' 。 此时会话变量'username'被找到。
@app.route('/login', methods = ['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action = "" method = "post">
<p><input type = text name = username/></p>
<p<<input type = submit value = Login/></p>
</form>
'''
该应用程序还包含一个logout()视图函数,弹出'username'会话变量。 因此, '/' URL再次显示开始页面。
@app.route('/logout')
def logout():
# remove the username from the session if it is there
session.pop('username', None)
return redirect(url_for('index'))
运行该应用程序并访问主页。 (确保设置应用程序的secret_key )
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = 'any random string’
输出将显示如下。 点击“click here to log in”链接。
该链接将被定向到另一个屏幕。 输入“admin”。
屏幕将显示消息'Logged in as admin' 。
Flask – Redirect & Errors
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
default status代码为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('log_in.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)
Flask类具有带有错误代码的abort()函数。
Flask.abort(code)
Code参数采用以下值之一 -
400 - 对于错误请求
401 - 未经验证的
403 - Forbidden
404 - 未找到
406 - 不可接受
415 - 对于不支持的媒体类型
429 - 请求太多
让我们在上面的代码中对login()函数稍作修改。 如果要显示'Unauthourized'页面,请将其替换为abort(401)调用abort(401) ,而不是重新显示登录页面。
from flask import Flask, redirect, url_for, render_template, request, abort
app = Flask(__name__)
@app.route('/')
def index():
return render_template('log_in.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)
Flask – Message Flashing
一个好的基于GUI的应用程序向用户提供有关交互的反馈。 例如,桌面应用程序使用对话框或消息框,JavaScript使用警报用于类似目的。
在Flask Web应用程序中生成这样的信息性消息很容易。 Flask框架的闪烁系统可以在一个视图中创建消息,并在名为next的视图函数中呈现它。
Flask模块包含flash()方法。 它将消息传递给下一个请求,该请求通常是一个模板。
flash(message, category)
这里,
message参数是要刷新的实际消息。
category参数是可选的。 它可以是'错误','信息'或'警告'。
为了从会话中删除消息,模板调用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 %}
现在让我们看一个简单的例子,演示Flask中的闪烁机制。 在以下代码中, '/' URL显示登录页面的链接,没有消息要闪存。
@app.route('/')
def index():
return render_template('index.html')
该链接将用户引导至'/login' URL,该URL显示登录表单。 提交后, login()视图函数会验证用户名和密码,并相应地闪烁'success'消息或创建'error'变量。
@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)
如果出现error ,将重新显示登录模板并显示错误消息。
Login.html
<!doctype html>
<html>
<body>
<h1>Login</h1>
{% if error %}
<p><strong>Error:</strong> {{ error }}
{% endif %}
<form action = "" method = post>
<dl>
<dt>Username:</dt>
<dd>
<input type = text name = username
value = "{{request.form.username }}">
</dd>
<dt>Password:</dt>
<dd><input type = password name = password></dd>
</dl>
<p><input type = submit value = Login></p>
</form>
</body>
</html>
另一方面,如果login成功,则会在索引模板上刷新成功消息。
Index.html
<!doctype html>
<html>
<head>
<title>Flask Message flashing</title>
</head>
<body>
{% 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>
</body>
</html>
Flask消息闪烁示例的完整代码如下 -
Flash.py
from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__)
app.secret_key = 'random string'
@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 。 将显示一条消息“您已成功登录”。
Flask – File Uploading
在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>
您将看到如下所示的屏幕。
选择文件后单击“ Submit 。 Form的post方法调用'/upload_file' 。 底层函数uploader()执行保存操作。
以下是Flask应用程序的Python代码。
from flask import Flask, render_template, request
from werkzeug import secure_filename
app = Flask(__name__)
@app.route('/upload')
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']
f.save(secure_filename(f.filename))
return 'file uploaded successfully'
if __name__ == '__main__':
app.run(debug = True)
Flask – Extensions
Flask通常被称为微框架,因为核心功能包括基于Werkzeug WSGI和路由以及基于Jinja2模板引擎。 此外,Flask框架支持cookie和会话以及JSON ,静态文件等Web帮助程序。显然,这还不足以开发完整的Web应用程序。 这是Flask扩展的图片。 Flask扩展为Flask框架提供了可扩展性。
有大量的Flask扩展可用。 Flask扩展是一个Python模块,它为Flask应用程序添加了特定类型的支持。 Flask Extension Registry是一个可用的扩展目录。 可以通过pip实用程序下载所需的扩展名。
在本教程中,我们将讨论以下重要的Flask扩展 -
Flask Mail - 为Flask应用程序提供SMTP接口
Flask WTF - 添加WTForms的渲染和验证
Flask SQLAlchemy - 为Flask应用程序添加SQLAlchemy支持
Flask Sijax - Flask 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 – Mail
基于Web的应用程序通常需要具有向用户/客户端发送邮件的功能。 Flask-Mail扩展使得与任何电子邮件服务器建立简单的界面变得非常容易。
首先,应该在pip实用程序的帮助下安装Flask-Mail扩展。
pip install Flask-Mail
然后需要通过设置以下应用程序参数的值来配置Flask-Mail。
Sr.No | 参数和描述 |
---|---|
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模块包含以下重要类的定义。
邮件课
它管理电子邮件消息传递要求。 类构造函数采用以下形式 -
flask-mail.Mail(app = None)
构造函数将Flask应用程序对象作为参数。
邮件类的方法
Sr.No | 方法和描述 |
---|---|
1 | send() 发送Message类对象的内容 |
2 | connect() 打开与邮件主机的连接 |
3 | send_message() 发送消息对象 |
消息类
它封装了一封电子邮件。 Message类构造函数有几个参数 -
flask-mail.Message(subject, recipients, body, html, sender, cc, bcc,
reply-to, date, charset, extra_headers, mail_options, rcpt_options)
消息类方法
attach() - 为邮件添加附件。 此方法采用以下参数 -
filename - 要附加的文件的名称
content_type - 文件的MIME类型
data - 原始文件数据
disposition - 内容处置,如果有的话。
add_recipient() - 向邮件添加另一个收件人
在以下示例中,Google的gmail服务的SMTP服务器用作Flask-Mail配置的MAIL_SERVER。
Step 1 - 在代码中从flask-mail模块导入Mail和Message类。
from flask_mail import Mail, Message
Step 2 - 然后根据以下设置配置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'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
Step 3 - 创建Mail类的实例。
mail = Mail(app)
Step 4 - 在由URL规则('/')映射的Python函数中设置Message对象。
@app.route("/")
def index():
msg = Message('Hello', sender = 'yourId@gmail.com', recipients = ['id1@gmail.com'])
msg.body = "This is the email body"
mail.send(msg)
return "Sent"
Step 5 - 整个代码如下。 在Python Shell中运行以下脚本并访问http://localhost:5000/.
from flask import Flask
from flask_mail import Mail, Message
app =Flask(__name__)
mail=Mail(app)
app.config['MAIL_SERVER']='smtp.gmail.com'
app.config['MAIL_PORT'] = 465
app.config['MAIL_USERNAME'] = 'yourId@gmail.com'
app.config['MAIL_PASSWORD'] = '*****'
app.config['MAIL_USE_TLS'] = False
app.config['MAIL_USE_SSL'] = True
mail = Mail(app)
@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)
请注意,Gmail服务中的内置不安全功能可能会阻止此登录尝试。 您可能必须降低安全级别。 请登录您的Gmail帐户并访问this链接以降低安全性。
Flask – WTF
Web应用程序的一个重要方面是为用户提供用户界面。 HTML提供了一个《form》标签,用于设计界面。 可以适当地使用Form’s元素,例如文本输入,收音机,选择等。
用户输入的数据以Http请求消息的形式通过GET或POST方法提交给服务器端脚本。
服务器端脚本必须从http请求数据重新创建表单元素。 因此,实际上,表单元素必须定义两次 - 一次在HTML中,另一次在服务器端脚本中。
使用HTML表单的另一个缺点是很难(如果不是不可能的话)动态呈现表单元素。 HTML本身无法验证用户的输入。
这就是WTForms ,一个灵活的表单,渲染和验证库,方便使用。 Flask-WTF扩展为这个WTForms库提供了一个简单的接口。
使用Flask-WTF ,我们可以在Python脚本中定义表单字段,并使用HTML模板进行渲染。 还可以将验证应用于WTF字段。
让我们看看HTML的动态生成是如何工作的。
首先,需要安装Flask-WTF扩展。
pip install flask-WTF
已安装的软件包包含Form类,该类必须用作用户定义表单的父级。
WTforms包包含各种表单字段的定义。 下面列出了一些Standard form fields 。
Sr.No | 标准表格字段和说明 |
---|---|
1 | TextField 表示 HTML表单元素 |
2 | BooleanField 表示 HTML表单元素 |
3 | DecimalField 用于显示带小数的数字的文本字段 |
4 | IntegerField TextField用于显示整数 |
5 | RadioField 表示 HTML表单元素 |
6 | SelectField 表示选择表单元素 |
7 | TextAreaField 表示 |
8 | PasswordField 表示 HTML表单元素 |
9 | SubmitField 表示表单元素 |
例如,包含文本字段的表单可以设计如下 -
from flask_wtf import Form
from wtforms import TextField
class ContactForm(Form):
name = TextField("Name Of Student")
除'name'字段外,还会自动创建CSRF令牌的隐藏字段。 这是为了防止Cross Site Request Forgery攻击。
渲染时,这将产生一个等效的HTML脚本,如下所示。
<input id = "csrf_token" name = "csrf_token" type = "hidden" />
<label for = "name">Name Of Student</label><br>
<input id = "name" name = "name" type = "text" value = "" />
Flask应用程序中使用用户定义的表单类,并使用模板呈现表单。
from flask import Flask, render_template
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'
@app.route('/contact')
def contact():
form = ContactForm()
return render_template('contact.html', form = form)
if __name__ == '__main__':
app.run(debug = True)
WTForms包还包含验证器类。 它对表单字段应用验证很有用。 以下列表显示了常用的验证器。
Sr.No | 验证器类和描述 |
---|---|
1 | DataRequired 检查输入字段是否为空 |
2 | 检查字段中的文本是否遵循电子邮件ID约定 |
3 | IPAddress 验证输入字段中的IP地址 |
4 | Length 验证输入字段中字符串的长度是否在给定范围内 |
5 | NumberRange 验证给定范围内输入字段中的数字 |
6 | URL 验证在输入字段中输入的URL |
我们现在将以联系表格的name字段应用'DataRequired'验证规则。
name = TextField("Name Of Student",[validators.Required("Please enter your name.")])
如果验证失败,表单对象的validate()函数将验证表单数据并抛出验证错误。 Error消息将发送到模板。 在HTML模板中,动态呈现错误消息。
{% for message in form.name.errors %}
{{ message }}
{% endfor %}
以下示例演示了上面给出的概念。 Contact form的设计如下(forms.py) 。
from flask_wtf import Form
from wtforms import TextField, IntegerField, TextAreaField, SubmitField, RadioField,
SelectField
from wtforms import validators, ValidationError
class ContactForm(Form):
name = TextField("Name Of Student",[validators.Required("Please enter
your name.")])
Gender = RadioField('Gender', choices = [('M','Male'),('F','Female')])
Address = TextAreaField("Address")
email = TextField("Email",[validators.Required("Please enter your email address."),
validators.Email("Please enter your email address.")])
Age = IntegerField("age")
language = SelectField('Languages', choices = [('cpp', 'C++'),
('py', 'Python')])
submit = SubmitField("Send")
验证器应用于“ Name和“ Email字段。
下面给出了Flask应用程序脚本(formexample.py) 。
from flask import Flask, render_template, request, flash
from forms import ContactForm
app = Flask(__name__)
app.secret_key = 'development key'
@app.route('/contact', methods = ['GET', 'POST'])
def contact():
form = ContactForm()
if request.method == 'POST':
if form.validate() == False:
flash('All fields are required.')
return render_template('contact.html', form = form)
else:
return render_template('success.html')
elif request.method == 'GET':
return render_template('contact.html', form = form)
if __name__ == '__main__':
app.run(debug = True)
模板的脚本(contact.html)如下 -
<!doctype html>
<html>
<body>
<h2 style = "text-align: center;">Contact Form</h2>
{% for message in form.name.errors %}
<div>{{ message }}</div>
{% endfor %}
{% for message in form.email.errors %}
<div>{{ message }}</div>
{% endfor %}
<form action = "http://localhost:5000/contact" method = post>
<fieldset>
<legend>Contact Form</legend>
{{ form.hidden_tag() }}
<div style = font-size:20px; font-weight:bold; margin-left:150px;>
{{ form.name.label }}<br>
{{ form.name }}
<br>
{{ form.Gender.label }} {{ form.Gender }}
{{ form.Address.label }}<br>
{{ form.Address }}
<br>
{{ form.email.label }}<br>
{{ form.email }}
<br>
{{ form.Age.label }}<br>
{{ form.Age }}
<br>
{{ form.language.label }}<br>
{{ form.language }}
<br>
{{ form.submit }}
</div>
</fieldset>
</form>
</body>
</html>
在Python shell中运行formexample.py并访问URL http://localhost:5000/contact 。 Contact表格将显示如下。
如果有任何错误,页面将如下所示 -
如果没有错误,将会呈现'success.html' 。
Flask – SQLite
Python有一个内置的SQlite支持。 SQlite3模块附带Python发行版。 有关在Python中使用SQLite数据库的详细教程,请参阅此链接 。 在本节中,我们将了解Flask应用程序如何与SQLite交互。
创建一个SQLite数据库'database.db'并在其中创建学生表。
import sqlite3
conn = sqlite3.connect('database.db')
print "Opened database successfully";
conn.execute('CREATE TABLE students (name TEXT, addr TEXT, city TEXT, pin TEXT)')
print "Table created successfully";
conn.close()
我们的Flask应用程序有三个View功能。
第一个new_student()函数绑定到URL规则('/addnew') 。 它呈现包含学生信息表单的HTML文件。
@app.route('/enternew')
def new_student():
return render_template('student.html')
'student.html'的HTML脚本如下 -
<html>
<body>
<form action = "{{ url_for('addrec') }}" method = "POST">
<h3>Student Information</h3>
Name<br>
<input type = "text" name = "nm" /></br>
Address<br>
<textarea name = "add" ></textarea><br>
City<br>
<input type = "text" name = "city" /><br>
PINCODE<br>
<input type = "text" name = "pin" /><br>
<input type = "submit" value = "submit" /><br>
</form>
</body>
</html>
可以看出,表单数据被发布到绑定addrec()函数的'/addrec' 。
这个addrec()函数通过POST方法检索表单的数据,并插入学生表中。 与插入操作中的成功或错误相对应的消息将呈现为'result.html' 。
@app.route('/addrec',methods = ['POST', 'GET'])
def addrec():
if request.method == 'POST':
try:
nm = request.form['nm']
addr = request.form['add']
city = request.form['city']
pin = request.form['pin']
with sql.connect("database.db") as con:
cur = con.cursor()
cur.execute("INSERT INTO students (name,addr,city,pin)
VALUES (?,?,?,?)",(nm,addr,city,pin) )
con.commit()
msg = "Record successfully added"
except:
con.rollback()
msg = "error in insert operation"
finally:
return render_template("result.html",msg = msg)
con.close()
result.html的HTML脚本包含一个转义语句{{msg}} ,它显示Insert操作的结果。
<!doctype html>
<html>
<body>
result of addition : {{ msg }}
<h2><a href = "\">go back to home page</a></h2>
</body>
</html>
该应用程序包含另一个由'/list'表示的list()函数。 它将'rows'填充为包含学生表中所有记录的MultiDict对象。 此对象将传递给list.html模板。
@app.route('/list')
def list():
con = sql.connect("database.db")
con.row_factory = sql.Row
cur = con.cursor()
cur.execute("select * from students")
rows = cur.fetchall();
return render_template("list.html",rows = rows)
此list.html是一个模板,它遍历行集并在HTML表中呈现数据。
<!doctype html>
<html>
<body>
<table border = 1>
<thead>
<td>Name</td>
<td>Address>/td<
<td>city</td>
<td>Pincode</td>
</thead>
{% for row in rows %}
<tr>
<td>{{row["name"]}}</td>
<td>{{row["addr"]}}</td>
<td> {{ row["city"]}}</td>
<td>{{row['pin']}}</td>
</tr>
{% endfor %}
</table>
<a href = "/">Go back to home page</a>
</body>
</html>
最后, '/' URL规则呈现'home.html' ,它充当应用程序的入口点。
@app.route('/')
def home():
return render_template('home.html')
这是Flask-SQLite应用程序的完整代码。
from flask import Flask, render_template, request
import sqlite3 as sql
app = Flask(__name__)
@app.route('/')
def home():
return render_template('home.html')
@app.route('/enternew')
def new_student():
return render_template('student.html')
@app.route('/addrec',methods = ['POST', 'GET'])
def addrec():
if request.method == 'POST':
try:
nm = request.form['nm']
addr = request.form['add']
city = request.form['city']
pin = request.form['pin']
with sql.connect("database.db") as con:
cur = con.cursor()
cur.execute("INSERT INTO students (name,addr,city,pin)
VALUES (?,?,?,?)",(nm,addr,city,pin) )
con.commit()
msg = "Record successfully added"
except:
con.rollback()
msg = "error in insert operation"
finally:
return render_template("result.html",msg = msg)
con.close()
@app.route('/list')
def list():
con = sql.connect("database.db")
con.row_factory = sql.Row
cur = con.cursor()
cur.execute("select * from students")
rows = cur.fetchall();
return render_template("list.html",rows = rows)
if __name__ == '__main__':
app.run(debug = True)
从Python shell运行此脚本,并在开发服务器开始运行时运行。 访问http://localhost:5000/在浏览器中显示如下的简单菜单 -
点击'Add New Record'链接以打开Student Information表单。
填写表单字段并提交。 底层函数将记录插入学生表中。
返回主页,然后单击'Show List'链接。 将显示显示样本数据的表格。
Flask – SQLAlchemy
在Flask Web应用程序中使用原始SQL在数据库上执行CRUD操作可能很繁琐。 相反, SQLAlchemy是一个功能强大的OR Mapper ,它为应用程序开发人员提供了SQL的全部功能和灵活性。 Flask-SQLAlchemy是Flask扩展,它将对SQLAlchemy的支持添加到Flask应用程序中。
What is ORM (Object Relation Mapping)?
大多数编程语言平台都是面向对象的 另一方面,RDBMS服务器中的数据存储为表格。 对象关系映射是一种将对象参数映射到底层RDBMS表结构的技术。 ORM API提供了执行CRUD操作的方法,而无需编写原始SQL语句。
在本节中,我们将研究Flask-SQLAlchemy的ORM技术并构建一个小型Web应用程序。
Step 1 - 安装Flask-SQLAlchemy扩展。
pip install flask-sqlalchemy
Step 2 - 您需要从此模块导入SQLAlchemy类。
from flask_sqlalchemy import SQLAlchemy
Step 3 - 现在创建Flask应用程序对象并为要使用的数据库设置URI。
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'
Step 4 - 然后使用应用程序对象作为参数创建SQLAlchemy类的对象。 该对象包含ORM操作的辅助函数。 它还提供了一个父Model Model类,用于声明用户定义的模型。 在下面的代码段中,创建了students模型。
db = SQLAlchemy(app)
class students(db.Model):
id = db.Column('student_id', db.Integer, primary_key = True)
name = db.Column(db.String(100))
city = db.Column(db.String(50))
addr = db.Column(db.String(200))
pin = db.Column(db.String(10))
def __init__(self, name, city, addr,pin):
self.name = name
self.city = city
self.addr = addr
self.pin = pin
Step 5 - 要创建/使用URI中提到的数据库,请运行create_all()方法。
db.create_all()
SQLAlchemy的Session对象管理ORM对象的所有持久性操作。
以下会话方法执行CRUD操作 -
db.session.add (模型对象) - 将记录插入到映射表中
db.session.delete (模型对象) - 从表中删除记录
model.query.all() - 从表中检索所有记录(对应于SELECT查询)。
您可以使用filter属性将筛选器应用于检索到的记录集。 例如,为了在学生表中检索city = 'Hyderabad'记录,请使用以下语句 -
Students.query.filter_by(city = ’Hyderabad’).all()
有了这么多背景,现在我们将为我们的应用程序提供视图函数来添加学生数据。
应用程序的入口点是绑定到'/' URL的show_all()函数。 记录集学生表作为参数发送到HTML模板。 模板中的服务器端代码以HTML表格形式呈现记录。
@app.route('/')
def show_all():
return render_template('show_all.html', students = students.query.all() )
模板的HTML脚本('show_all.html')是这样的 -
<!DOCTYPE html>
<html lang = "en">
<head></head>
<body>
<h3>
<a href = "{{ url_for('show_all') }}">Comments - Flask
SQLAlchemy example</a>
</h3>
<hr/>
{%- for message in get_flashed_messages() %}
{{ message }}
{%- endfor %}
<h3>Students (<a href = "{{ url_for('new') }}">Add Student
</a>)</h3>
<table>
<thead>
<tr>
<th>Name</th>
<th>City</th>
<th>Address</th>
<th>Pin</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr>
<td>{{ student.name }}</td>
<td>{{ student.city }}</td>
<td>{{ student.addr }}</td>
<td>{{ student.pin }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
上面的页面包含指向'/new' URL映射new()函数的超链接。 单击时,将打开“学生信息”表单。 数据在POST方法中发布到相同的URL。
new.html
<!DOCTYPE html>
<html>
<body>
<h3>Students - Flask SQLAlchemy example</h3>
<hr/>
{%- for category, message in get_flashed_messages(with_categories = true) %}
<div class = "alert alert-danger">
{{ message }}
</div>
{%- endfor %}
<form action = "{{ request.path }}" method = "post">
<label for = "name">Name</label><br>
<input type = "text" name = "name" placeholder = "Name" /><br>
<label for = "email">City</label><br>
<input type = "text" name = "city" placeholder = "city" /><br>
<label for = "addr">addr</label><br>
<textarea name = "addr" placeholder = "addr"></textarea><br>
<label for = "PIN">City</label><br>
<input type = "text" name = "pin" placeholder = "pin" /><br>
<input type = "submit" value = "Submit" />
</form>
</body>
</html>
当检测到http方法为POST时,表单数据将添加到学生表中,应用程序将返回显示添加数据的主页。
@app.route('/new', methods = ['GET', 'POST'])
def new():
if request.method == 'POST':
if not request.form['name'] or not request.form['city'] or not request.form['addr']:
flash('Please enter all the fields', 'error')
else:
student = students(request.form['name'], request.form['city'],
request.form['addr'], request.form['pin'])
db.session.add(student)
db.session.commit()
flash('Record was successfully added')
return redirect(url_for('show_all'))
return render_template('new.html')
下面给出了完整的应用程序代码(app.py) 。
from flask import Flask, request, flash, url_for, redirect, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'
app.config['SECRET_KEY'] = "random string"
db = SQLAlchemy(app)
class students(db.Model):
id = db.Column('student_id', db.Integer, primary_key = True)
name = db.Column(db.String(100))
city = db.Column(db.String(50))
addr = db.Column(db.String(200))
pin = db.Column(db.String(10))
def __init__(self, name, city, addr,pin):
self.name = name
self.city = city
self.addr = addr
self.pin = pin
@app.route('/')
def show_all():
return render_template('show_all.html', students = students.query.all() )
@app.route('/new', methods = ['GET', 'POST'])
def new():
if request.method == 'POST':
if not request.form['name'] or not request.form['city'] or not request.form['addr']:
flash('Please enter all the fields', 'error')
else:
student = students(request.form['name'], request.form['city'],
request.form['addr'], request.form['pin'])
db.session.add(student)
db.session.commit()
flash('Record was successfully added')
return redirect(url_for('show_all'))
return render_template('new.html')
if __name__ == '__main__':
db.create_all()
app.run(debug = True)
从Python shell运行脚本,并在浏览器中输入http://localhost:5000/ 。
单击'Add Student'链接以打开Student information表单。
填写表格并提交。 主页重新显示提交的数据。
我们可以看到输出如下所示。
Flask – Sijax
Sijax代表'Simple Ajax' ,它是一个Python/jQuery库,旨在帮助您轻松地将Ajax引入您的应用程序。 它使用jQuery.ajax来发出AJAX请求。
安装 (Installation)
Flask-Sijax的安装很简单。
pip install flask-sijax
配置 (Configuration)
SIJAX_STATIC_PATH - 您希望镜像Sijax javascript文件的静态路径。 默认位置是static/js/sijax 。 在此文件夹中, sijax.js和json2.js文件。
SIJAX_JSON_URI - 从中加载json2.js静态文件的URI
Sijax使用JSON在浏览器和服务器之间传递数据。 这意味着浏览器需要本机支持JSON或从json2.js文件获得JSON支持。
以这种方式注册的函数不能提供Sijax功能,因为默认情况下无法使用POST方法访问它们(并且Sijax使用POST请求)。
要使View函数能够处理Sijax请求,可以使用@app.route('/url', methods = ['GET', 'POST'])通过POST访问它@app.route('/url', methods = ['GET', 'POST'])或者像这样使用@flask_sijax.route帮助装饰器 -
@flask_sijax.route(app, '/hello')
每个Sijax处理函数(像这一个)都会自动接收至少一个参数,就像Python将'self'传递给对象方法一样。 'obj_response'参数是函数回复浏览器的方式。
def say_hi(obj_response):
obj_response.alert('Hi there!')
当检测到Sijax请求时,Sijax会像这样处理它 -
g.sijax.register_callback('say_hi', say_hi)
return g.sijax.process_request()
Sijax应用程序
最小的Sijax应用程序代码如下所示 -
import os
from flask import Flask, g
from flask_sijax import sijax
path = os.path.join('.', os.path.dirname(__file__), 'static/js/sijax/')
app = Flask(__name__)
app.config['SIJAX_STATIC_PATH'] = path
app.config['SIJAX_JSON_URI'] = '/static/js/sijax/json2.js'
flask_sijax.Sijax(app)
@app.route('/')
def index():
return 'Index'
@flask_sijax.route(app, '/hello')
def hello():
def say_hi(obj_response):
obj_response.alert('Hi there!')
if g.sijax.is_sijax_request:
# Sijax request detected - let Sijax handle it
g.sijax.register_callback('say_hi', say_hi)
return g.sijax.process_request()
return _render_template('sijaxexample.html')
if __name__ == '__main__':
app.run(debug = True)
当Sijax向服务器请求(特殊的jQuery.ajax()请求)时, g.sijax.is_sijax_request()在服务器上检测到此请求,在这种情况下,您让Sijax处理请求。
使用g.sijax.register_callback()注册的所有函数g.sijax.register_callback()公开,以便从浏览器进行调用。
调用g.sijax.process_request()告诉Sijax执行适当的(以前注册的)函数并将响应返回给浏览器。
Flask – Deployment
外部可见服务器
开发服务器上的Flask应用程序只能在设置了开发环境的计算机上访问。 这是默认行为,因为在调试模式下,用户可以在计算机上执行任意代码。
如果禁用debug ,则可以通过将主机名设置为'0.0.0.0' ,使本地计算机上的开发服务器可供网络上的用户使用。
app.run(host = ’0.0.0.0’)
因此,您的操作系统将侦听所有公共IP。
部署(Deployment)
要从开发环境切换到成熟的生产环境,需要在真实的Web服务器上部署应用程序。 根据您的具体情况,可以使用不同的选项来部署Flask Web应用程序。
对于小型应用程序,您可以考虑在以下任何托管平台上部署它,所有这些平台都为小型应用程序提供免费计划。
- Heroku
- dotcloud
- webfaction
Flask应用程序可以部署在这些云平台上。 此外,可以在Google云平台上部署Flask应用程序。 Localtunnel服务允许您在localhost上共享您的应用程序,而不会弄乱DNS和防火墙设置。
如果您倾向于使用专用Web服务器代替上述共享平台,则可以使用以下选项进行探索。
mod_wsgi
mod_wsgi是一个Apache模块,它提供了一个WSGI兼容接口,用于在Apache服务器上托管基于Python的Web应用程序。
安装mod_wsgi
要直接从PyPi安装官方发行版,您可以运行 -
pip install mod_wsgi
要验证安装是否成功,请使用start-server命令运行mod_wsgi-express脚本 -
mod_wsgi-express start-server
这将在端口8000上启动Apache/mod_wsgi。然后,您可以通过将浏览器指向 - 来验证安装是否有效 -
http://localhost:8000/
创建.wsgi文件
应该有一个yourapplication.wsgi文件。 此文件包含代码mod_wsgi,该代码在启动时执行以获取应用程序对象。 对于大多数应用程序,以下文件应该足够了 -
from yourapplication import app as application
确保您的应用程序和所有正在使用的库都在python加载路径上。
配置Apache
您需要告诉mod_wsgi,您的应用程序的位置。
<VirtualHost *>
ServerName example.com
WSGIScriptAlias/C:\yourdir\yourapp.wsgi
<Directory C:\yourdir>
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
独立的WSGI容器
有很多流行的服务器用Python编写,包含WSGI应用程序并提供HTTP服务。
- Gunicorn
- Tornado
- Gevent
- 扭曲的网络
Flask – FastCGI
FastCGI是Nginix,lighttpd和Cherokee等Web服务器上Flask应用程序的另一个部署选项。
配置FastCGI
首先,您需要创建FastCGI服务器文件。 我们称之为yourapplication.fcgiC 。
from flup.server.fcgi import WSGIServer
from yourapplication import app
if __name__ == '__main__':
WSGIServer(app).run()
nginx和旧版本的lighttpd需要显式传递套接字以与FastCGI服务器通信。 为此,您需要将路径的路径传递给WSGIServer 。
WSGIServer(application, bindAddress = '/path/to/fcgi.sock').run()
配置Apache
对于基本的Apache部署, .fcgi文件将出现在您的应用程序URL中,例如example.com/yourapplication.fcgi/hello/ 。 配置应用程序的方法很少,因此yourapplication.fcgi不会出现在URL中。
<VirtualHost *>
ServerName example.com
ScriptAlias//path/to/yourapplication.fcgi/
</VirtualHost>
配置lighttpd
lighttpd基本配置如下所示 -
fastcgi.server = ("/yourapplication.fcgi" => ((
"socket" => "/tmp/yourapplication-fcgi.sock",
"bin-path" => "/var/www/yourapplication/yourapplication.fcgi",
"check-local" => "disable",
"max-procs" => 1
)))
alias.url = (
"/static/" => "/path/to/your/static"
)
url.rewrite-once = (
"^(/static($|/.*))$" => "$1",
"^(/.*)$" => "/yourapplication.fcgi$1"
)
请记住启用FastCGI ,别名和重写模块。 此配置将应用程序绑定到/yourapplication的应用程序。