Flask 快速指南
Flask - 概述
什么是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作为其基础之一。
Jinga2
Jinja2是Python的一个流行的模板引擎。Web模板系统将模板与特定数据源组合以呈现动态网页。
Flask通常被称为微框架。它旨在保持应用程序的核心简单而可扩展。Flask没有用于数据库处理的内置抽象层,也没有形成验证支持。相反,Flask支持扩展以向应用程序添加此类功能。一些流行的Flask扩展将在本教程后面讨论。
Flask - 环境
安装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 - 应用
为了测试 Flask 安装,请在编辑器中将以下代码输入 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构造函数使用当前模块(__name __)的名称作为参数。
Flask类的route()函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。
app.route(rule, options)
rule 参数表示与该函数的URL绑定。
options 是要转发给基础Rule对象的参数列表。
在上面的示例中,'/ ' URL与hello_world()函数绑定。因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。
最后,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服务器。 |
上面给出的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应用程序。但是,当应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。为避免这种不便,请启用调试支持。如果代码更改,服务器将自行重新加载。它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有的话)。
在运行或将调试参数传递给run()方法之前,通过将application对象的debug属性设置为True来启用Debug模式。
app.debug = True app.run() app.run(debug = True)
烧瓶 - 路由
现代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 - 变量规则
可以通过向规则参数添加可变部分来动态构建URL。 此可变部分标记为< variable-name> 。 它作为关键字参数传递到与规则相关联的函数。
在以下示例中, route()装饰器的规则参数包含附加到URL \'/ hello\'的< name> 因此,如果在浏览器中输入 http:// localhost:5000 / hello / TutorialsPoint 作为 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 / TutorialsPoint。
以下输出将在浏览器中显示。
Hello TutorialsPoint!
除了默认字符串变量部分之外,还可以使用以下转换器构建规则:
Sr.No | 转换器 描述 |
---|---|
1 | int 接受整数 |
2 | float 浮点值 |
3 | 路径 接受用作目录分隔符的斜杠 |
在下面的代码中,使用所有这些构造函数。
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运行上面的代码。 访问浏览器中的网址 http:// localhost:5000 / blog / 11 。
给定的数字用作 show_blog()函数的参数。 浏览器显示以下输出 -
Blog Number 11
在浏览器中输入此网址 - 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 / 网址会产生 404未找到 页。
Flask - URL构建
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参数。
保存上面的代码并从Python shell运行。
打开浏览器并输入网址为 - http:// localhost:5000 / hello / admin
在浏览器中的应用程序响应是 -
Hello Admin
在浏览器中输入以下网址 - http:// localhost:5000 / hello / mvl
应用程序响应现在更改为 -
Hello mvl as Guest
Flask - HTTP方法
Http协议是万维网中数据通信的基础。 在此协议中定义了从指定的URL检索不同的数据方法。
下表总结了不同的http方法 -
Sr.No | 方法&amp; 描述 |
---|---|
1 | GET 以未加密的形式将数据发送到服务器。 最常用的方法。 |
2 | HEAD 和GET一样,但没有响应体 |
3 | POST 用于将HTML表单数据发送到服务器。 POST方法接收的数据不由服务器缓存。 |
4 | PUT 用所上传的内容替换目标资源的所有当前表示。 |
5 | 删除 删除由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,然后单击提交。
表单数据被发送到表单标签的action子句中的URL。
http:// localhost / login 映射到 login()函数。 由于服务器通过 POST 方法接收数据,从表单数据获得的“nm”参数的值通过 -
user = request.form['nm']
它作为可变部分传递给\'/ success\' URL。 浏览器在窗口中显示欢迎消息。
将 login.html 中的方法参数更改为\'GET\',然后在浏览器中再次打开。 在服务器上接收的数据是通过 GET 方法。 \'nm\'参数的值现在通过 -
User = request.args.get(‘nm’)
这里, args 是包含表单参数及其对应值对的列表的字典对象。 与\'nm\'参数对应的值将像之前一样传递到\'/ success\'URL。
烧瓶 - 模板
可以以HTML的形式返回绑定到某个URL的函数的输出。 例如,在以下脚本中, hello()函数将使用&lt; h1&gt; 标签呈现\'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将尝试在templates文件夹中找到与此脚本所在的文件夹中的HTML文件。
- Application folder
- Hello.py
- templates
- hello.html
术语\'web模板系统\'是指设计一个HTML脚本,其中可以动态插入变量数据。 web模板系统包括模板引擎,某种数据源和模板处理器。
Flask使用 jinja2 模板引擎。 Web模板包含用于变量和表达式(在这些情况下为Python表达式)的HTML语法分散的占位符,在呈现模板时,这些占位符是替换的值。
以下代码在模板文件夹中另存为 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 / hello / mvl
网址的变量部分插入到 {{name}} 占位符。
jinja2 模板引擎使用以下定界符从HTML转义。
- {% ... %} for Statements
- {{ ... }} for Expressions to print to the template output
- {# ... #} for Comments not included in the template output
- # ... ## for Line Statements
在下面的示例中,演示了在模板中使用条件语句。 到 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脚本并访问网址 http:// localhost / hello / 60 ,然后访问 http:// localhost / hello / 30 ,查看有条件地更改HTML的输出。
Python循环结构也可以在模板中使用。 在以下脚本中,当网址 http:// localhost:5000 / result 时, result()函数会将字典对象发送到模板 results.html >在浏览器中打开。
result.html 的模板部分使用 for循环来呈现字典对象 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脚本作为 result.html 保存在templates文件夹中。
<!doctype html> <html> <body> <table border = 1> {% for key, value in result.iteritems() %} <tr> <th> {{ key }} </th> <td> {{ value }} </td> </tr> {% endfor %} </table> </body> </html>
这里,对应于 For 循环的Python语句也包含在{%..%}中,而表达式键和值 } 。
开发开始后,在浏览器中打开 http:// localhost:5000 / result 即可获得以下输出。
Flask - 静态文件
网络应用程序通常需要一个静态文件,例如支持显示网页的 javascript 文件或 CSS 文件。 通常,网络服务器配置为为您提供服务,但在开发过程中,这些文件是从您的软件包中的 static 文件夹或模块旁边提供的,并且可以从 i> / static 。
特殊的端点\'static\'用于为静态文件生成URL。
在下面的示例中, index.html 中的 OnClick HTML事件按钮调用 hello.js 中定义的 / b>,它显示在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 - 请求对象
来自客户端网页的数据作为全局请求对象发送到服务器。 为了处理请求数据,它应该从Flask模块导入。
请求对象的重要属性如下所列 -
表单 - 它是一个字典对象,包含表单参数的键和值对及其值。
args - 在问号(?)后面的URL的一部分的查询字符串的解析内容。
Cookie - 保存Cookie名称和值的字典对象。
文件 - 与上传的文件有关的数据。
方法 - 当前请求方法。
Flask - 将表单数据发送到模板
我们已经看到,可以在URL规则中指定http方法。 触发函数接收的 Form 数据可以以字典对象的形式收集它并将其转发到模板以在相应的网页上呈现它。
在以下示例中,\'/\'网址会呈现具有表单的网页(student.html)。 填入的数据会发布到触发 result()函数的\'/ result\'网址。
results()函数收集呈现在 request.form 中的表单数据,并将其发送给 result.html 。
模板动态呈现形式数据的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.iteritems() %} <tr> <th> {{ key }} </th> <td> {{ value }} </td> </tr> {% endfor %} </table> </body> </html>
运行Python脚本,并在浏览器中输入网址 http:// localhost:5000 / 。
当点击提交按钮时,表单数据以HTML表格的形式呈现在 result.html 上。
烧瓶 - 曲奇饼
Cookie以文本文件的形式存储在客户端的计算机上。 其目的是记住和跟踪与客户的使用相关的数据,以获得更好的访问者体验和网站统计信息。
请求对象包含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\' URL。 相关联的视图函数设置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的输出如下所示。
烧瓶 - 会话
与Cookie不同,会话数据存储在服务器上。 会话是客户端登录到服务器并注销它的时间间隔。 需要在该会话中保存的数据存储在服务器上的临时目录中。
与每个客户端的会话都分配有会话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’
输出将显示如下所示。 点击链接“点击此处登录”。
链接将被定向到另一个屏幕。 键入“admin”。
屏幕将显示消息“以管理员身份登录”。
Flask - 重定向&amp; 错误
Flask类有一个 redirect()函数。 调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。
redirect()函数的原型如下 -
Flask.redirect(location, statuscode, response)
在上述函数中 -
location 参数是应重定向响应的网址。
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('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)
代码参数采用以下值之一:
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('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 - 消息闪烁
好的基于GUI的应用程序向用户提供关于交互的反馈。 例如,桌面应用程序使用对话框或消息框,JavaScript使用警报用于类似目的。
在Flask Web应用程序中生成这样的信息性消息很容易。 Flask框架的闪烁系统使得可以在一个视图中创建消息,并在称为下一的视图函数中呈现它。
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。 提交时, 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)
如果出现错误,则会重新显示登录模板,并显示错误消息。
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)
执行上述代码后,您将看到如下所示的屏幕。
当您点击链接,您将被定向到登录页面。
输入用户名和密码。
点击登录。 将显示一条消息“您已成功登录”。
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.html\'的\'/ upload\'网址规则,以及\'/ upload-file\' 调用 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>
您将看到如下所示的屏幕。
选择文件后,单击提交。 表单的后方法调用\'/ 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 - 扩展
Flask通常被称为微框架,因为核心功能包括基于 Werkzeug 的WSGI和路由以及基于 Jinja2 的模板引擎。 此外,Flask框架还支持cookie和会话,以及像 JSON ,静态文件等Web帮助。显然,这不足以开发一个成熟的Web应用程序。 这是Flask扩展在哪里。 Flask扩展为Flask框架提供了可扩展性。
有大量的Flask扩展可用。 Flask扩展是一个Python模块,它向Flask应用程序添加特定类型的支持。 Flask扩展注册表是可用的扩展的目录。 所需的扩展程序可以通过 pip 实用程序下载。
在本教程中,我们将讨论以下重要的Flask扩展 -
Flask Mail - 为Flask应用程序提供SMTP接口
Flask WTF - 添加了WTForms的渲染和验证
Flask SQLAlchemy - 为Flask应用程序添加SQLAlchemy支持
Flask Sijax - Sijax的接口 - Python / jQuery库,使AJAX易于在Web应用程序中使用
每种类型的扩展通常提供有关其使用的广泛文档。 由于扩展是一个Python模块,它需要导入才能使用。 瓶子延伸部分通常命名为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 扩展功能可以很容易地与任何电子邮件服务器建立简单的界面。
首先,Flask-Mail扩展应该在pip实用程序的帮助下安装。
pip install Flask-Mail
然后Flask-Mail需要通过设置以下应用程序参数的值进行配置。
Sr.No | 参数&amp; 描述 |
---|---|
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应用程序对象作为参数。
Mail类的方法
Sr.No | 方法&amp; 描述 |
---|---|
1 | send() 发送消息类对象的内容 |
2 | connect() 打开与邮件主机的连接 |
3 | send_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 - 原始文件数据
处置 - 内容处置(如果有)。
add_recipient() - 向邮件中添加另一个收件人
在下面的示例中,Google gmail服务的SMTP服务器用作Flask-Mail配置的MAIL_SERVER。
步骤1 - 从代码中的邮箱模块导入邮件和邮件类。
from flask_mail import Mail, Message
步骤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
步骤3 - 创建Mail类的实例。
mail = Mail(app)
步骤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"
步骤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帐户,然后访问此链接,以减少 安全。
烧瓶 - WTF
Web应用程序的一个重要方面是为用户提供一个用户界面。 HTML提供了一个&lt; form&gt; 标签,用于设计接口。 可以适当地使用表单元素,例如文本输入,广播,选择等。
由用户输入的数据以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 包中包含各种表单字段的定义。 下面列出了一些标准表单字段。
Sr.No | 标准表格字段&amp; 描述 |
---|---|
1 | TextField 表示&lt; input type =\'text\'&gt; HTML表单元素 |
2 | BooleanField 表示&lt; input type =\'checkbox\'&gt; HTML表单元素 |
3 | DecimalField 用于显示带小数的数字的文本框 |
4 | IntegerField 用于显示整数的TextField |
5 | RadioField 表示&lt; input type =\'radio\'&gt; HTML表单元素 |
6 | SelectField 表示选择表单元素 |
7 | TextAreaField 表示&lt; testarea&gt; html表单元素 |
8 | PasswordField 表示&lt; input type =\'password\'&gt; HTML表单元素 |
9 | SubmitField 表示&lt; input type =\'submit\'&gt; 表单元素 |
例如,包含文本字段的表单可以设计如下 -
from flask_wtf import Form from wtforms import TextField class ContactForm(Form): name = TextField("Name Of Student")
除了\'name\'字段,自动创建CSRF令牌的隐藏字段。 这是为了防止跨站点请求伪造攻击。
呈现时,这将导致等效的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 | 验证器类&amp; 描述 |
---|---|
1 | DataRequired 检查输入字段是否为空 |
2 | 电子邮件 检查字段中的文本是否符合电子邮件ID约定 |
3 | IP地址 在输入字段中验证IP地址 |
4 | 长度 验证输入字段中的字符串长度是否在给定范围内 |
5 | NumberRange 在给定范围内验证输入字段中的数字 |
6 | 网址 验证在输入字段中输入的URL |
现在,我们将对联系表单中的 name 字段应用\'DataRequired\'验证规则。
name = TextField("Name Of Student",[validators.Required("Please enter your name.")])
表单对象的 validate()函数验证表单数据,并在验证失败时抛出验证错误。 错误消息将发送到模板。 在HTML模板中,错误消息是动态呈现的。
{% for message in form.name.errors %} {{ message }} {% endfor %}
以下示例演示了上面给出的概念。 联系表单的设计如下(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")
验证器会应用到名称和电子邮件字段。
下面给出了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 。 将显示联系人表单,如下所示。
如果有任何错误,页面将看起来像这样 -
如果没有错误,将显示\'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应用程序有三个查看功能。
第一个 new_student()函数已绑定到网址规则(\'/ 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\' URL。
此 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}} 。
<!doctype html> <html> <body> result of addition : {{ msg }} <h2><a href = "\">go back to home page</a></h2> </body> </html>
应用程序包含由\'/ list\' URL表示的另一个 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>
最后,\'/\'网址规则呈现一个\'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 / ,显示一个简单的菜单 -
点击“添加新记录”链接以打开学生信息表单。
填写表单字段并提交。 底层函数在学生表中插入记录。
返回首页,然后点击\'显示列表\'链接。 将显示显示样品数据的表。
Flask - SQLAlchemy
在Flask Web应用程序中使用原始SQL对数据库执行CRUD操作可能很乏味。 相反, SQLAlchemy ,Python工具包是一个强大的 OR Mapper ,为应用程序开发人员提供了SQL的全部功能和灵活性。 Flask-SQLAlchemy是Flask扩展,为SQLAlchemy应用程序添加了对SQLAlchemy的支持。
什么是ORM(对象关系映射)?
大多数编程语言平台是面向对象的。 另一方面,RDBMS服务器中的数据存储为表。 对象关系映射是将对象参数映射到底层RDBMS表结构的技术。 ORM API提供了执行CRUD操作的方法,而不必编写原始SQL语句。
在本节中,我们将研究Flask-SQLAlchemy的ORM技术并构建一个小型Web应用程序。
步骤1 - 安装Flask-SQLAlchemy扩充功能。
pip install flask-sqlalchemy
步骤2 - 您需要从此模块导入SQLAlchemy类。
from flask_sqlalchemy import SQLAlchemy
步骤3 - 现在创建一个Flask应用程序对象并设置要使用的数据库的URI。
app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'
步骤4 - 然后创建一个SQLAlchemy类的对象,以应用程序对象作为参数。 此对象包含用于ORM操作的辅助函数。 它还提供了一个父Model类,使用它来声明用户定义的模型。 在下面的代码段中,创建了学生模型。
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
步骤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() )
模板(\'show_all.html\')的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\'网址映射 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 / 。
点击“添加学生”链接以打开学生信息表单。
填写表单并提交。 主页将重新显示提交的数据。
我们可以看到输出如下所示。
烧瓶 - Sijax
Sijax 代表\'Simple Ajax\',它是一个 Python / jQuery 库,旨在帮助您轻松地将 Ajax 到您的应用程序。 它使用 jQuery.ajax 来创建AJAX请求。
安装
安装Flask-Sijax很容易。
pip install flask-sijax
组态
SIJAX_STATIC_PATH - 您希望对Sijax javascript文件进行镜像的静态路径。 默认位置为 static / js / sijax 。 在此文件夹中,保存 sijax.js 和 json2.js 文件。
SIJAX_JSON_URI - 用于加载json2.js静态文件的URI
Sijax使用 JSON 在浏览器和服务器之间传递数据。 这意味着浏览器需要或从 json2.js 文件本身支持 JSON 或获取 JSON 支持。
以此方式注册的函数不能提供 Sijax 功能,因为它们在默认情况下不能使用 POST 方法访问(而Sijax使用POST请求)。
要使 View 功能能够处理 Sijax 请求,请使用 @ 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!')
当检测到Ajax请求时,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()检测到, case你让 Sijax 处理请求。
使用 g.sijax.register_callback()注册的所有函数都可以从浏览器调用。
调用 g.sijax.process_request()会告诉Sijax执行相应的(先前注册的)函数并将响应返回给浏览器。
烧瓶 - 部署
外部可见服务器
开发服务器上的Flask应用程序只能在设置开发环境的计算机上访问。 这是一种默认行为,因为在调试模式下,用户可以在计算机上执行任意代码。
如果禁用了 debug ,则可以通过将主机名设置为\'0.0.0.0\',使本地计算机上的开发服务器对网络上的用户可用。
app.run(host = ’0.0.0.0’)
因此,您的操作系统侦听所有公共IP。
部署
要从开发环境切换到完整的生产环境,应用程序需要部署在真实的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
这将启动Apache / mod_wsgi在端口8000.然后您可以验证安装工作通过指向您的浏览器 -
http://localhost:8000/
正在创建.wsgi文件
应该有一个 yourapplication.wsgi 文件。 此文件包含代码 mod_wsgi,,它在启动时执行以获取应用程序对象。 对于大多数应用程序,以下文件应该足够 -
from yourapplication import app as application
确保 yourapplication 和所有正在使用的库都在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
- Twisted Web
Flask - FastCGI
FastCGI是在像nginx,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 文件将显示在应用程序网址中。 example.com/yourapplication.fcgi/hello / 。 有几种方法可以配置您的应用程序,以使 yourapplication.fcgi 不会显示在网址中。
<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 。
更多建议: