Flask 简明教程
Flask – Overview
What is Web Framework?
Web 应用程序框架或简单的 Web 框架代表了一组库和模块,它使 Web 应用程序开发人员能够编写应用程序,而不必考虑低级细节(例如协议、线程管理等)。
Web Application Framework or simply Web Framework represents a collection of libraries and modules that enables a web application developer to write applications without having to bother about low-level details such as protocols, thread management etc.
What is Flask?
Flask 是用 Python 编写的 Web 应用程序框架。它是由 Armin Ronacher 开发的,他领导着一个名为 Pocco 的国际 Python 爱好者团体。Flask 基于 Werkzeug WSGI 工具包和 Jinja2 模板引擎。这两个都是 Pocco 项目。
Flask is a web application framework written in Python. It is developed by Armin Ronacher, who leads an international group of Python enthusiasts named Pocco. Flask is based on the Werkzeug WSGI toolkit and Jinja2 template engine. Both are Pocco projects.
WSGI
Web 服务器网关接口 (WSGI)已被采纳为 Python Web 应用程序开发的标准。WSGI 是 Web 服务器和 Web 应用程序之间通用接口的规范。
Web Server Gateway Interface (WSGI) has been adopted as a standard for Python web application development. WSGI is a specification for a universal interface between the web server and the web applications.
Werkzeug
它是 WSGI 工具包,能实现请求、响应对象和其他实用程序功能。这样便可以在其基础上构建 Web 框架。Flask 框架将 Werkzeug 用作其中一个基础。
It is a WSGI toolkit, which implements requests, response objects, and other utility functions. This enables building a web framework on top of it. The Flask framework uses Werkzeug as one of its bases.
Jinja2
Jinja2 是 Python 的一个流行模板引擎。Web 模板系统将模板与特定数据源结合以呈现动态 Web 页面。
Jinja2 is a popular templating engine for Python. A web templating system combines a template with a certain data source to render dynamic web pages.
Flask 通常被称为微框架。它旨在保持应用程序内核简单且可扩展。Flask 没有用于处理数据库的内置抽象层,也没有表单验证支持。相反,Flask 支持扩展来向应用程序添加此类功能。本教程的后面部分将讨论一些流行的 Flask 扩展。
Flask is often referred to as a micro framework. It aims to keep the core of an application simple yet extensible. Flask does not have built-in abstraction layer for database handling, nor does it have form a validation support. Instead, Flask supports the extensions to add such functionality to the application. Some of the popular Flask extensions are discussed later in the tutorial.
Flask – Environment
Prerequisite
通常需要 Python 2.6 或更高版本才能安装 Flask。尽管 Flask 及其依赖项可与 Python 3 配合良好 (Python 3.3 及更高版本),但许多 Flask 扩展都不支持它。因此,建议在 Python 2.7 上安装 Flask。
Python 2.6 or higher is usually required for installation of Flask. Although Flask and its dependencies work well with Python 3 (Python 3.3 onwards), many Flask extensions do not support it properly. Hence, it is recommended that Flask should be installed on Python 2.7.
Install virtualenv for development environment
virtualenv 是一个虚拟 Python 环境构建程序。它帮助用户并行创建多个 Python 环境。因此,它可以避免不同版本库之间的兼容性问题。
virtualenv is a virtual Python environment builder. It helps a user to create multiple Python environments side-by-side. Thereby, it can avoid compatibility issues between the different versions of the libraries.
以下命令可安装 virtualenv
The following command installs virtualenv
pip install virtualenv
此命令需要管理员权限。在 Linux/Mac OS 上,添加 sudo pip 前。如果使用的是 Windows,请以管理员身份登录。在 Ubuntu 上,可以使用其软件包管理器来安装 virtualenv 。
This command needs administrator privileges. Add sudo before pip on Linux/Mac OS. If you are on Windows, log in as Administrator. On Ubuntu virtualenv may be installed using its package manager.
Sudo apt-get install virtualenv
安装后,会在文件夹中创建一个新的虚拟环境。
Once installed, new virtual environment is created in a folder.
mkdir newproj
cd newproj
virtualenv venv
要在 Linux/OS X 激活相应环境,请使用以下内容 -
To activate corresponding environment, on Linux/OS X, use the following −
venv/bin/activate
在 Windows 上,可以使用以下内容
On Windows, following can be used
venv\scripts\activate
现在我们可以准备在此环境中安装 Flask。
We are now ready to install Flask in this environment.
pip install Flask
可直接运行以上命令,无需用于系统级安装的虚拟环境。
The above command can be run directly, without virtual environment for system-wide installation.
Flask – Application
为了检测 Flask 的安装情况,请在编辑器中输入以下代码作为 Hello.py
In order to test Flask installation, type the following code in the editor as 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 应用程序。
Importing flask module in the project is mandatory. An object of Flask class is our WSGI application.
Flask 构造器将 current module (name) 的名称作为参数。
Flask constructor takes the name of current module (name) as argument.
Flask 类的 route() 函数是一个装饰器,它告诉应用程序哪个 URL 应调用关联函数。
The route() function of the Flask class is a decorator, which tells the application which URL should call the associated function.
app.route(rule, options)
-
The rule parameter represents URL binding with the function.
-
The options is a list of parameters to be forwarded to the underlying Rule object.
原文中的URL ‘/’ 与函数 hello_world() 关联绑定。因此,当在浏览器中打开网络服务器的主页时,该函数的输出数据将被渲染出来。
In the above example, ‘/’ URL is bound with hello_world() function. Hence, when the home page of web server is opened in browser, the output of this function will be rendered.
最后,Flask 类中的 run() 方法将应用程序运行于本地开发服务器上。
Finally the run() method of Flask class runs the application on the local development server.
app.run(host, port, debug, options)
所有参数都是可选的
All parameters are optional
Sr.No. |
Parameters & Description |
1 |
host Hostname to listen on. Defaults to 127.0.0.1 (localhost). Set to ‘0.0.0.0’ to have server available externally |
2 |
port Defaults to 5000 |
3 |
debug Defaults to false. If set to true, provides a debug information |
4 |
options To be forwarded to underlying Werkzeug server. |
上述 Python 脚本是通过 Python shell 执行的。
The above given Python script is executed from Python shell.
Python Hello.py
Python shell 中显示的信息表明你
A message in Python shell informs you that
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
在浏览器中打开上述 URL (localhost:5000) 。 ‘Hello World’ 消息将显示于其上。
Open the above URL (localhost:5000) in the browser. ‘Hello World’ message will be displayed on it.
Debug mode
通过调用 run() 方法启动一个 Flask 应用程序。然而,在应用程序的开发阶段,每次代码有变化时,都应手动重新启动应用程序。为了避免这种情况带来的不便,可以启用 debug support 。之后,如果代码有变化,服务器将自行重新载入。它还将提供一个有用的调试器,用于追踪应用程序中存在的任何错误。
A Flask application is started by calling the run() method. However, while the application is under development, it should be restarted manually for each change in the code. To avoid this inconvenience, enable debug support. The server will then reload itself if the code changes. It will also provide a useful debugger to track the errors if any, in the application.
启用 Debug 模式需要在运行或向 run() 方法传递 debug 参数之前,将 application 对象的 debug 属性设置为 True 。
The Debug mode is enabled by setting the debug property of the application object to True before running or passing the debug parameter to the run() method.
app.debug = True
app.run()
app.run(debug = True)
Flask – Routing
现代网络框架使用路由技术来帮助用户记住应用程序 URL。这对于直接访问目标页面非常有用,而无需从主页进行导航。
Modern web frameworks use the routing technique to help a user remember application URLs. It is useful to access the desired page directly without having to navigate from the home page.
Flask 中的 route() 装饰器用于将 URL 与一个函数进行绑定。例如 −
The route() decorator in Flask is used to bind URL to a function. For example −
@app.route(‘/hello’)
def hello_world():
return ‘hello world’
在这里,URL ‘/hello’ 规则被绑定至 hello_world() 函数。因此,如果用户访问 http://localhost:5000/hello URL, hello_world() 函数的输出数据将在浏览器中渲染出来。
Here, URL ‘/hello’ rule is bound to the hello_world() function. As a result, if a user visits http://localhost:5000/hello URL, the output of the hello_world() function will be rendered in the browser.
某个应用程序对象中的 add_url_rule() 函数还可以用于将 URL 与函数进行绑定,如同在上述示例中使用 route() 的情况。
The add_url_rule() function of an application object is also available to bind a URL with a function as in the above example, route() is used.
以下表示法也可以实现装饰器的目的 −
A decorator’s purpose is also served by the following representation −
def hello_world():
return ‘hello world’
app.add_url_rule(‘/’, ‘hello’, hello_world)
Flask – Variable Rules
通过在规则参数中添加可变部分,可以动态构建一个 URL。该可变部分被标记为 <variable-name> 。将它作为关键字参数传递给该规则关联的函数。
It is possible to build a URL dynamically, by adding variable parts to the rule parameter. This variable part is marked as <variable-name>. It is passed as a keyword argument to the function with which the rule is associated.
在以下的示例中, route() 装饰器的规则参数中包含 <name> 可变部分,连接至 URL ‘/hello’ 。因此,如果将 http://localhost:5000/hello/TutorialsPoint 输入为浏览器中的 URL ,那么 ‘TutorialPoint’ 将被作为参数提供给 hello() 函数。
In the following example, the rule parameter of route() decorator contains <name> variable part attached to URL ‘/hello’. Hence, if the http://localhost:5000/hello/TutorialsPoint is entered as a URL in the browser, ‘TutorialPoint’ will be supplied to hello() function as argument.
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.
Save the above script as hello.py and run it from Python shell. Next, open the browser and enter URL http://localhost:5000/hello/TutorialsPoint.
浏览器中会显示以下输出。
The following output will be displayed in the browser.
Hello TutorialsPoint!
除了默认的字符串变量部分,还可以使用以下转换器构造规则 -
In addition to the default string variable part, rules can be constructed using the following converters −
Sr.No. |
Converters & Description |
1 |
int accepts integer |
2 |
float For floating point value |
3 |
path accepts slashes used as directory separator character |
在以下代码中,将使用所有这些构造器。
In the following code, all these constructors are used.
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 。
Run the above code from Python Shell. Visit the URL http://localhost:5000/blog/11 in the browser.
给定的数字被用作 show_blog() 函数的参数。浏览器显示以下输出 -
The given number is used as argument to the show_blog() function. The browser displays the following output −
Blog Number 11
在浏览器中输入这个 URL - http://localhost:5000/rev/1.1
Enter this URL in the browser − http://localhost:5000/rev/1.1
revision() 函数将浮点数作为参数。浏览器窗口中会显示以下结果 -
The revision() function takes up the floating point number as argument. The following result appears in the browser window −
Revision Number 1.100000
Flask 的 URL 规则基于 Werkzeug’s 路由模块。这会确保形成的 URL 唯一并且基于 Apache 规定的优先级。
The URL rules of Flask are based on Werkzeug’s routing module. This ensures that the URLs formed are unique and based on precedents laid down by Apache.
考虑在以下脚本中定义的规则 −
Consider the rules defined in the following script −
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 页面。
Both the rules appear similar but in the second rule, trailing slash (/) is used. As a result, it becomes a canonical URL. Hence, using /python or /python/ returns the same output. However, in case of the first rule, /flask/ URL results in 404 Not Found page.
Flask – URL Building
url_for() 函数对于为特定函数动态构建 URL 非常有用。此函数接收函数名称作为第一个参数,并接收一个或多个关键字参数,每个都对应着 URL 的变量部分。
The url_for() function is very useful for dynamically building a URL for a specific function. The function accepts the name of a function as first argument, and one or more keyword arguments, each corresponding to the variable part of URL.
以下脚本展示了 url_for() 函数的用法。
The following script demonstrates use of url_for() function.
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 中传递给它的参数的值。
The above script has a function user(name) which accepts a value to its argument from the URL.
User() 函数检查收到的参数是否与 ‘admin’ 匹配。如果匹配,则使用 url_for() 将应用程序重新定向到 hello_admin() 函数,否则将把收到的参数作为 guest 参数传递到 hello_guest() 函数。
The User() function checks if an argument received matches ‘admin’ or not. If it matches, the application is redirected to the hello_admin() function using url_for(), otherwise to the hello_guest() function passing the received argument as guest parameter to it.
保存上述代码并从 Python shell 运行。
Save the above code and run from Python shell.
打开浏览器并输入 URL 为 − http://localhost:5000/user/admin
Open the browser and enter URL as − http://localhost:5000/user/admin
浏览器中的应用程序响应为 −
The application response in browser is −
Hello Admin
在浏览器中输入以下 URL − http://localhost:5000/user/mvl
Enter the following URL in the browser − http://localhost:5000/user/mvl
应用程序响应现在更改为 −
The application response now changes to −
Hello mvl as Guest
Flask – HTTP methods
Http 协议是万维网中数据通信的基础。此协议中定义了不同方法才能从指定 URL 检索数据。
Http protocol is the foundation of data communication in world wide web. Different methods of data retrieval from specified URL are defined in this protocol.
下表总结了不同的 http 方法 −
The following table summarizes different http methods −
Sr.No. |
Methods & Description |
1 |
GET Sends data in unencrypted form to the server. Most common method. |
2 |
HEAD Same as GET, but without response body |
3 |
POST Used to send HTML form data to server. Data received by POST method is not cached by server. |
4 |
PUT Replaces all current representations of the target resource with the uploaded content. |
5 |
DELETE Removes all current representations of the target resource given by a URL |
默认情况下,Flask 路由响应 GET 请求。然而,可以通过向 route() 装饰器提供 methods 参数来更改此首选项。
By default, the Flask route responds to the GET requests. However, this preference can be altered by providing methods argument to route() decorator.
为了说明如何在 URL 路由中使用 POST 方法,首先让我们创建一个 HTML 表单,并使用 POST 方法将表单数据发送至 URL。
In order to demonstrate the use of POST method in URL routing, first let us create an HTML form and use the POST method to send form data to a URL.
将以下脚本保存为 login.html
Save the following script as 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 中输入以下脚本。
Now enter the following script in 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 。
After the development server starts running, open login.html in the browser, enter name in the text field and click Submit.
表单数据通过 form 标记的动作子句 POST 至 URL。
Form data is POSTed to the URL in action clause of form tag.
http://localhost/login 映射至 login() 函数。由于服务器通过 POST 方法接收了数据,因此可通过以下方式获取从表单数据中获取的“nm”参数值:
http://localhost/login is mapped to the login() function. Since the server has received data by POST method, value of ‘nm’ parameter obtained from the form data is obtained by −
user = request.form['nm']
它作为变量部分传递至 ‘/success’ URL。浏览器在窗口中显示 welcome 消息。
It is passed to ‘/success’ URL as variable part. The browser displays a welcome message in the window.
在 login.html 中将方法参数更改为 ‘GET’ ,并在浏览器中再次将其打开。服务器上收到的数据通过 GET 方法。现在可通过以下方式获取“nm”参数值:
Change the method parameter to ‘GET’ in login.html and open it again in the browser. The data received on server is by the GET method. The value of ‘nm’ parameter is now obtained by −
User = request.args.get(‘nm’)
此处, args 是包含表单参数及其对应值的列表对的字典对象。与之前一样,与“nm”参数对应的值传递给“/success”URL。
Here, args is dictionary object containing a list of pairs of form parameter and its corresponding value. The value corresponding to ‘nm’ parameter is passed on to ‘/success’ URL as before.
Flask – Templates
可以以 HTML 形式返回绑定至某个 URL 的函数的输出。例如,在以下脚本中, hello() 函数将使用附加了 <h1> 标记的 ‘Hello World’ 呈现。
It is possible to return the output of a function bound to a certain URL in the form of HTML. For instance, in the following script, hello() function will render ‘Hello World’ with <h1> tag attached to it.
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。
However, generating HTML content from Python code is cumbersome, especially when variable data and Python language elements like conditionals or loops need to be put. This would require frequent escaping from HTML.
这正是我们可以利用 Flask 所基于的 Jinja2 模板引擎的地方。可以使用 render_template() 函数呈现 HTML 文件,而不从函数返回硬编码的 HTML。
This is where one can take advantage of Jinja2 template engine, on which Flask is based. Instead of returning hardcode HTML from the function, a HTML file can be rendered by the render_template() function.
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 文件,该文件夹与该脚本存在的文件夹相同。
Flask will try to find the HTML file in the templates folder, in the same folder in which this script is present.
-
Application folder Hello.pytemplates hello.html
术语 ‘web templating system’ 涉及设计 HTML 脚本,可在其中动态插入变量数据。Web 模板系统包含一个模板引擎、某种数据源和一个模板处理器。
The term ‘web templating system’ refers to designing an HTML script in which the variable data can be inserted dynamically. A web template system comprises of a template engine, some kind of data source and a template processor.
Flask 使用 Jinja2 模板引擎。Web 模板包含 HTML 语法,其中插入用于变量和表达式(在这些情况下是 Python 表达式)的占位符,模板呈现时将替换为值。
Flask uses Jinja2 template engine. A web template contains HTML syntax interspersed placeholders for variables and expressions (in these case Python expressions) which are replaced values when the template is rendered.
以下代码作为 hello.html 保存到模板文件夹中。
The following code is saved as hello.html in the templates folder.
<!doctype html>
<html>
<body>
<h1>Hello {{ name }}!</h1>
</body>
</html>
接下来,从 Python shell 运行以下脚本。
Next, run the following script from 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
As the development server starts running, open the browser and enter URL as − http://localhost:5000/hello/mvl
URL 的 variable 部分插入到 {{ name }} 占位符中。
The variable part of URL is inserted at {{ name }} place holder.
Jinja2 模板引擎使用以下分隔符转义 HTML。
The Jinja2 template engine uses the following delimiters for escaping from 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。
In the following example, use of conditional statement in the template is demonstrated. The URL rule to the hello() function accepts the integer parameter. It is passed to the hello.html template. Inside it, the value of number received (marks) is compared (greater or less than 50) and accordingly HTML is conditionally rendered.
Python 脚本如下 −
The Python Script is as follows −
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 模板脚本如下 −
HTML template script of hello.html is as follows −
<!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 用分隔符 {%..%} 括起来。
Note that the conditional statements if-else and endif are enclosed in delimiter {%..%}.
运行 Python 脚本并访问 URL http://localhost/hello/60 ,然后访问 http://localhost/hello/30 ,以查看 HTML 按条件更改的输出。
Run the Python script and visit URL http://localhost/hello/60 and then http://localhost/hello/30 to see the output of HTML changing conditionally.
Python 循环构造也可以在模板内部使用。在以下脚本中,当在浏览器中打开 URL http://localhost:5000/result 时,函数 result() 将一个字典对象发送到模板 results.html 。
The Python loop constructs can also be employed inside the template. In the following script, the result() function sends a dictionary object to template results.html when URL http://localhost:5000/result is opened in the browser.
result.html 的模板部分使用 for loop ,以将字典对象 result{} 的键值对作为 HTML 表格的单元格来呈现。
The Template part of result.html employs a for loop to render key and value pairs of dictionary object result{} as cells of an HTML table.
从 Python Shell 中运行以下代码。
Run the following code from 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 ,放在模板文件夹中。
Save the following HTML script as result.html in the templates folder.
<!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 则放在 {{ }} 中。
Here, again the Python statements corresponding to the For loop are enclosed in {%..%} whereas, the expressions key and value are put inside {{ }}.
开发开始运行后,在浏览器中打开 http://localhost:5000/result ,以获取以下输出。
After the development starts running, open http://localhost:5000/result in the browser to get the following output.
Flask – Static Files
Web 应用程序通常需要一个静态文件,如 javascript 文件或 CSS 文件支持 Web 页面的显示。通常,Web 服务器被配置为为您提供它们,但在开发期间,这些文件是从包中的静态文件夹或模块旁边提供,并且可以在应用程序的 /static 上使用。
A web application often requires a static file such as a javascript file or a CSS file supporting the display of a web page. Usually, the web server is configured to serve them for you, but during the development, these files are served from static folder in your package or next to your module and it will be available at /static on the application.
一个特殊的端点“static”用于生成静态文件的 URL。
A special endpoint ‘static’ is used to generate URL for static files.
在以下示例中,在 hello.js 中定义的 javascript 函数在 index.html 中的 HTML 按钮的 OnClick 事件上调用,该按钮在 ‘/’ Flask 应用程序的 URL 上呈现。
In the following example, a javascript function defined in hello.js is called on OnClick event of HTML button in index.html, which is rendered on ‘/’ URL of the Flask application.
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 脚本如下所示。
The HTML script of index.html is given below.
<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() 函数。
hello.js contains sayHello() function.
function sayHello() {
alert("Hello World")
}
Flask – Request Object
客户网页中的数据以全局请求对象的形式发送到服务器。为了处理请求数据,应从 Flask 模块导入它。
The data from a client’s web page is sent to the server as a global request object. In order to process the request data, it should be imported from the Flask module.
请求对象的重要属性如下列出:
Important attributes of request object are listed below −
-
Form − It is a dictionary object containing key and value pairs of form parameters and their values.
-
args − parsed contents of query string which is part of URL after question mark (?).
-
Cookies − dictionary object holding Cookie names and values.
-
files − data pertaining to uploaded file.
-
method − current request method.
Flask – Sending Form Data to Template
我们已经看到,可以在 URL 规则中指定 http 方法。触发函数收到的 Form 数据可以以字典对象的形式收集,并将其转发到模板以便在相应的网页上渲染它。
We have already seen that the http method can be specified in URL rule. The Form data received by the triggered function can collect it in the form of a dictionary object and forward it to a template to render it on a corresponding web page.
在下面的示例中, ‘/’ URL 渲染一个包含表单的网页 (student.html)。填写其中的数据将发布到 ‘/result’ URL,该 URL 会触发 result() 函数。
In the following example, ‘/’ URL renders a web page (student.html) which has a form. The data filled in it is posted to the ‘/result’ URL which triggers the result() function.
results() 函数会以字典对象收集 request.form 中存在的表单数据,然后将其发送给 result.html 进行渲染。
The results() function collects form data present in request.form in a dictionary object and sends it for rendering to result.html.
模板会动态渲染 form 数据的 HTML 表格。
The template dynamically renders an HTML table of form data.
以下是应用程序的 Python 代码:
Given below is the Python code of application −
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 脚本:
Given below is the HTML script of student.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) 的代码:
Code of template (result.html) is given below −
<!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/ 。
Run the Python script and enter the URL http://localhost:5000/ in the browser.
当点击 Submit 按钮时,表单数据以 HTML 表格形式呈现在 result.html 上。
When the Submit button is clicked, form data is rendered on result.html in the form of HTML table.
Flask – Cookies
Cookie 以文本文件形式存储在客户端计算机上。其目的是记住并跟踪与客户端使用相关的数据,以便提供更好的访问者体验和网站统计信息。
A cookie is stored on a client’s computer in the form of a text file. Its purpose is to remember and track data pertaining to a client’s usage for better visitor experience and site statistics.
一个 Request object 包含 Cookie 的属性。它是一个包含所有 Cookie 变量及其对应值的对象字典,这些变量及其对应值是由客户端传输的。此外,Cookie 还存储了它的过期时间、路径和网站的域名。
A Request object contains a cookie’s attribute. It is a dictionary object of all the cookie variables and their corresponding values, a client has transmitted. In addition to it, a cookie also stores its expiry time, path and domain name of the site.
在 Flask 中,Cookie 设置在响应对象上。使用 make_response() 函数从视图函数的返回值中获取响应对象。然后,使用响应对象的 set_cookie() 函数存储一个 Cookie。
In Flask, cookies are set on response object. Use make_response() function to get response object from return value of a view function. After that, use the set_cookie() function of response object to store a cookie.
读回 Cookie 非常容易。 get() 属性的 request.cookies 方法用于读取 Cookie。
Reading back a cookie is easy. The get() method of request.cookies attribute is used to read a cookie.
在下面的 Flask 应用中,当您访问 ‘/’ URL 时,会弹出一个简单的表单。
In the following Flask application, a simple form opens up as you visit ‘/’ URL.
@app.route('/')
def index():
return render_template('index.html')
此 HTML 页面包含一个文本输入。
This HTML page contains one text input.
<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 并呈示另一个页面。
The Form is posted to ‘/setcookie’ URL. The associated view function sets a Cookie name userID and renders another page.
@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 值。
‘readcookie.html’ contains a hyperlink to another view function getcookie(), which reads back and displays the cookie value in browser.
@app.route('/getcookie')
def getcookie():
name = request.cookies.get('userID')
return '<h1>welcome '+name+'</h1>'
运行应用并访问 http://localhost:5000/
Run the application and visit http://localhost:5000/
设置一个 Cookie 的结果以这种方式显示 −
The result of setting a cookie is displayed like this −
读取回 Cookie 的输出显示如下。
The output of read back cookie is shown below.
Flask – Sessions
类似于 Cookie,会话数据存储在客户端。会话是指客户端登录到一个服务器并登出时的时段。在这段时间内需要保存的数据都存储在客户端浏览器中。
Like Cookie, Session data is stored on client. Session is the time interval when a client logs into a server and logs out of it. The data, which is needed to be held across this session, is stored in the client browser.
每个客户端的会话都会被分配一个 Session ID 。会话数据被存储在 Cookie 之上,并且服务器对其进行加密签名。对于这种加密,Flask 应用需要一个定义过的 SECRET_KEY 。
A session with each client is assigned a Session ID. The Session data is stored on top of cookies and the server signs them cryptographically. For this encryption, a Flask application needs a defined SECRET_KEY.
会话对象也是一个包含会话变量及其关联值的关键值对的对象字典。
Session object is also a dictionary object containing key-value pairs of session variables and associated values.
例如,要设置一个 ‘username’ 会话变量,请使用这条语句 −
For example, to set a ‘username’ session variable use the statement −
Session[‘username’] = ’admin’
要释放一个会话变量,请使用 pop() 方法。
To release a session variable use pop() method.
session.pop('username', None)
以下代码简单演示了会话在 Flask 中的工作。URL ‘/’ 仅仅提示用户登录,因为会话变量 ‘username’ 没有被设置。
The following code is a simple demonstration of session works in Flask. URL ‘/’ simply prompts user to log in, as session variable ‘username’ is not set.
@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 方法被调用,它会弹出一个登录表单。
As user browses to ‘/login’ the login() view function, because it is called through GET method, opens up a login form.
一个表单被提交回 ‘/login’ ,现在会话变量被设置。应用被重定向到 ‘/’ 。这一次找到了会话变量 ‘username’ 。
A Form is posted back to ‘/login’ and now session variable is set. Application is redirected to ‘/’. This time session variable ‘username’ is found.
@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 再次显示打开页面。
The application also contains a logout() view function, which pops out ‘username’ session variable. Hence, ‘/’ URL again shows the opening page.
@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 )
Run the application and visit the homepage. (Ensure to set secret_key of the application)
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = 'any random string’
输出如下所示。单击链接 “click here to log in” 。
The output will be displayed as shown below. Click the link “click here to log in”.
链接将被定向到另一个屏幕。输入 ‘admin’。
The link will be directed to another screen. Type ‘admin’.
屏幕会显示给你一条消息, ‘Logged in as admin’ 。
The screen will show you the message, ‘Logged in as admin’.
Flask – Redirect & Errors
Flask 类有一个 redirect() 函数。当被调用时,它返回一个响应对象,并且使用指定的HTTP状态码将用户重定向到另一个目标位置。
Flask class has a redirect() function. When called, it returns a response object and redirects the user to another target location with specified status code.
redirect() 函数的原型如下 −
Prototype of redirect() function is as below −
Flask.redirect(location, statuscode, response)
在上面的函数中 −
In the above function −
-
location parameter is the URL where response should be redirected.
-
statuscode sent to browser’s header, defaults to 302.
-
response parameter is used to instantiate response.
以下状态代码是标准化的 −
The following status codes are standardized −
-
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’ 。
The default status code is 302, which is for ‘found’.
在以下示例中, redirect() 函数用于在登录尝试失败时再次显示登录页面。
In the following example, the redirect() function is used to display the login page again when a login attempt fails.
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'))
else:
return redirect(url_for('index'))
@app.route('/success')
def success():
return 'logged in successfully'
if __name__ == '__main__':
app.run(debug = True)
Flask 类具有带错误代码的 abort() 函数。
Flask class has abort() function with an error code.
Flask.abort(code)
Code 参数采用以下值之一 −
The Code parameter takes one of following values −
-
400 − for Bad Request
-
401 − for Unauthenticated
-
403 − for Forbidden
-
404 − for Not Found
-
406 − for Not Acceptable
-
415 − for Unsupported Media Type
-
429 − Too Many Requests
让我们在上述代码中的 login() 函数中做一些小的更改。如果要显示 ‘Unauthourized’ 页面,请用调用 abort(401) 替换重新显示登录页面。
Let us make a slight change in the login() function in the above code. Instead of re-displaying the login page, if ‘Unauthourized’ page is to be displayed, replace it with call to 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 会使用警报以实现类似目的。
A good GUI based application provides feedback to a user about the interaction. For example, the desktop applications use dialog or message box and JavaScript uses alerts for similar purpose.
在 Flask Web 应用程序中,生成此类信息消息十分容易。Flask 框架的 Flashing 系统能够在一个视图中创建消息,并在名为 next 的视图函数中渲染它。
Generating such informative messages is easy in Flask web application. Flashing system of Flask framework makes it possible to create a message in one view and render it in a view function called next.
Flask 模块包含 flash() 方法。它将消息传递给下一个请求(通常是一个模板)。
A Flask module contains flash() method. It passes a message to the next request, which generally is a template.
flash(message, category)
在此,
Here,
-
message parameter is the actual message to be flashed.
-
category parameter is optional. It can be either ‘error’, ‘info’ or ‘warning’.
为了从会话中删除消息,模板会调用 get_flashed_messages() 。
In order to remove message from session, template calls get_flashed_messages().
get_flashed_messages(with_categories, category_filter)
这两个参数都是可选的。第一个参数是元组,如果接收到消息,则说明类型。第二个参数对仅显示特定消息很有用。
Both parameters are optional. The first parameter is a tuple if received messages are having category. The second parameter is useful to display only specific messages.
以下闪光灯收到了模板中的消息。
The following flashes received messages in a template.
{% with messages = get_flashed_messages() %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% endwith %}
我们现在来看一个简单的例子,演示 Flask 中闪烁机制的操作。在下面的代码中,一个 ‘/’ URL 显示指向登录页面的链接,没有要显示的消息。
Let us now see a simple example, demonstrating the flashing mechanism in Flask. In the following code, a ‘/’ URL displays link to the login page, with no message to flash.
@app.route('/')
def index():
return render_template('index.html')
这个链接将引导用户到 ‘/login’ URL,后者显示登录表单。提交后, login() 视图函数会验证用户名和密码,然后相应地闪烁 ‘success’ 消息或创建 ‘error’ 变量。
The link leads a user to ‘/login’ URL which displays a login form. When submitted, the login() view function verifies a username and password and accordingly flashes a ‘success’ message or creates ‘error’ variable.
@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 的情况下,重新显示登录模板并附有错误消息。
In case of error, the login template is redisplayed with error message.
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 成功,将在索引模板上闪烁一条成功消息。
On the other hand, if login is successful, a success message is flashed on the index template.
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 消息闪烁示例代码如下 −
A complete code for Flask message flashing example is given below −
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)
在执行上述代码后,您将看到如下所示的屏幕。
After executing the above codes, you will see the screen as shown below.
当您单击该链接时,您将被定向到登录页面。
When you click on the link, you will be directed to the Login page.
输入用户名和密码。
Enter the Username and password.
单击 Login 。一条消息“您已成功登录”将被显示。
Click Login. A message will be displayed “You were successfully logged in” .
Flask – File Uploading
在 Flask 中处理文件上传非常容易。它需要一个将 enctype 属性设置为“multipart/form-data”的 HTML 表单,将文件发布到 URL。URL 处理程序从 request.files[] 对象获取文件并将其保存到所需位置。
Handling file upload in Flask is very easy. It needs an HTML form with its enctype attribute set to ‘multipart/form-data’, posting the file to a URL. The URL handler fetches file from request.files[] object and saves it to the desired location.
每个上传的文件首先保存在服务器上的临时位置,然后才实际保存到其最终位置。目标文件的文件名可以硬编码,也可以从 request.files[file] 对象的 filename 属性获取。但是,建议使用 secure_filename() 函数获取其安全版本。
Each uploaded file is first saved in a temporary location on the server, before it is actually saved to its ultimate location. Name of destination file can be hard-coded or can be obtained from filename property of request.files[file] object. However, it is recommended to obtain a secure version of it using the secure_filename() function.
可以在 Flask 对象的配置设置中定义默认上传文件夹的路径和上传文件的大小。
It is possible to define the path of default upload folder and maximum size of uploaded file in configuration settings of Flask object.
app.config[‘UPLOAD_FOLDER’] |
Defines path for upload folder |
app.config[‘MAX_CONTENT_PATH’] |
Specifies maximum size of file yo be uploaded – in bytes |
以下代码具有 ‘/upload’ URL 规则,用于显示模板文件夹中的 ‘upload.html’ ,以及 ‘/upload-file’ URL 规则,用于调用 uploader() 函数处理上传过程。
The following code has ‘/upload’ URL rule that displays ‘upload.html’ from the templates folder, and ‘/upload-file’ URL rule that calls uploader() function handling upload process.
‘upload.html’ 有一个文件选择器按钮和一个提交按钮。
‘upload.html’ has a file chooser button and a submit button.
<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>
您将看到如下所示的屏幕。
You will see the screen as shown below.
选择文件后单击 Submit 。表单的 post 方法调用 ‘/upload_file’ URL。基础函数 uploader() 执行保存操作。
Click Submit after choosing file. Form’s post method invokes ‘/upload_file’ URL. The underlying function uploader() does the save operation.
下面是 Flask 应用程序的 Python 代码。
Following is the Python code of Flask application.
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 is often referred to as a micro framework, because a core functionality includes WSGI and routing based on Werkzeug and template engine based on Jinja2. In addition, Flask framework has support for cookie and sessions as well as web helpers like JSON, static files etc. Obviously, this is not enough for the development of a full-fledged web application. This is where the Flask extensions come in picture. Flask extensions give extensibility to Flask framework.
大量的 Flask 扩展可用。Flask 扩展是一个 Python 模块,它为 Flask 应用程序添加了特定类型支持。Flask 扩展注册表是一个可用的扩展目录。必需的扩展可以通过 pip 实用程序下载。
There are a large number of Flask extensions available. A Flask extension is a Python module, which adds specific type of support to the Flask application. Flask Extension Registry is a directory of extensions available. The required extension can be downloaded by pip utility.
在本教程中,我们将讨论以下重要的 Flask 扩展 −
In this tutorial, we will discuss the following important Flask extensions −
-
Flask Mail − provides SMTP interface to Flask application
-
Flask WTF − adds rendering and validation of WTForms
-
Flask SQLAlchemy − adds SQLAlchemy support to Flask application
-
Flask Sijax − Interface for Sijax - Python/jQuery library that makes AJAX easy to use in web applications
每种类型的扩展通常会提供关于其使用情况的详尽文档。由于扩展是一个 Python 模块,所以需要导入它才能使用它。Flask 扩展通常被命名为 flask-foo。要导入,
Each type of extension usually provides extensive documentation about its usage. Since an extension is a Python module, it needs to be imported for it to be used. Flask extensions are generally named as flask-foo. To import,
from flask_foo import [class, function]
对于 Flask 0.7 之后的版本,您也可以使用语法 −
For versions of Flask later than 0.7, you can also use the syntax −
from flask.ext import foo
对于此用法,需要激活一个兼容性模块。可以通过运行 flaskext_compat.py 来安装它
For this usage, a compatibility module needs to be activated. It can be installed by running flaskext_compat.py
import flaskext_compat
flaskext_compat.activate()
from flask.ext import foo
Flask – Mail
一个基于网络的应用程序常常需要一个向用户/客户端发送邮件的功能。 Flask-Mail 扩展使得使用任何电子邮件服务器设置一个简单的接口变得非常容易。
A web based application is often required to have a feature of sending mail to the users/clients. Flask-Mail extension makes it very easy to set up a simple interface with any email server.
首先,应该使用 pip 实用程序安装 Flask-Mail 扩展。
At first, Flask-Mail extension should be installed with the help of pip utility.
pip install Flask-Mail
然后,需要通过设置以下应用程序参数的值来配置 Flask-Mail。
Then Flask-Mail needs to be configured by setting values of the following application parameters.
Sr.No |
Parameters & Description |
1 |
MAIL_SERVER Name/IP address of email server |
2 |
MAIL_PORT Port number of server used |
3 |
MAIL_USE_TLS Enable/disable Transport Security Layer encryption |
4 |
MAIL_USE_SSL Enable/disable Secure Sockets Layer encryption |
5 |
MAIL_DEBUG Debug support. Default is Flask application’s debug status |
6 |
MAIL_USERNAME User name of sender |
7 |
MAIL_PASSWORD password of sender |
8 |
MAIL_DEFAULT_SENDER sets default sender |
9 |
MAIL_MAX_EMAILS Sets maximum mails to be sent |
10 |
MAIL_SUPPRESS_SEND Sending suppressed if app.testing set to true |
11 |
MAIL_ASCII_ATTACHMENTS If set to true, attached filenames converted to ASCII |
flask-mail 模块包含以下重要类的定义。
The flask-mail module contains definitions of the following important classes.
Mail class
它管理电子邮件消息传递的需求。该类的构造器采用以下形式 −
It manages email-messaging requirements. The class constructor takes the following form −
flask-mail.Mail(app = None)
构造器以 Flask 应用程序对象作为参数。
The Constructor takes the Flask application object as a parameter.
Methods of Mail class
Sr.No |
Methods & Description |
1 |
send() Sends contents of Message class object |
2 |
connect() Opens connection with mail host |
3 |
send_message() Sends message object |
Message class
它封装了一封电子邮件。Message 类的构造器有几个参数 −
It encapsulates an email message. Message class constructor has several parameters −
flask-mail.Message(subject, recipients, body, html, sender, cc, bcc,
reply-to, date, charset, extra_headers, mail_options, rcpt_options)
Message class methods
attach() − 向邮件添加附件。此方法采用以下参数 −
attach() − adds an attachment to message. This method takes the following parameters −
-
filename − name of file to attach
-
content_type − MIME type of file
-
data − raw file data
-
disposition − content disposition, if any.
add_recipient() − 向电子邮件添加另一位收件人
add_recipient() − adds another recipient to message
在以下示例中,将 Google Gmail 服务的 SMTP 服务器用作 Flask-Mail 配置的 MAIL_SERVER。
In the following example, SMTP server of Google’s gmail service is used as MAIL_SERVER for Flask-Mail configuration.
Step 1 − 在代码中从 flask-mail 模块导入 Mail 和 Message 类。
Step 1 − Import Mail and Message class from flask-mail module in the code.
from flask_mail import Mail, Message
Step 2 − 然后根据以下设置配置 Flask-Mail。
Step 2 − Then Flask-Mail is configured as per following settings.
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 类的一个实例。
Step 3 − Create an instance of Mail class.
mail = Mail(app)
Step 4 − 在由 URL 规则 (‘/’) 映射的 Python 函数中设置一个 Message 对象。
Step 4 − Set up a Message object in a Python function mapped by URL rule (‘/’).
@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/.
Step 5 − The entire code is given below. Run the following script in Python Shell and visit 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 链接以降低安全性。
Note that the built-insecurity features in Gmail service may block this login attempt. You may have to decrease the security level. Please log in to your Gmail account and visit this link to decrease the security.
Flask – WTF
Web 应用程序的基本方面之一是为用户提供用户界面。HTML 提供了一个 <form> 标记,用于设计界面。可以适当使用文本输入、单选按钮、选择等 Form’s 元素。
One of the essential aspects of a web application is to present a user interface for the user. HTML provides a <form> tag, which is used to design an interface. A Form’s elements such as text input, radio, select etc. can be used appropriately.
用户输入的数据通过 GET 或 POST 方法以 Http 请求消息的形式提交到服务器端脚本。
Data entered by a user is submitted in the form of Http request message to the server side script by either GET or POST method.
-
The Server side script has to recreate the form elements from http request data. So in effect, form elements have to be defined twice – once in HTML and again in the server side script.
-
Another disadvantage of using HTML form is that it is difficult (if not impossible) to render the form elements dynamically. HTML itself provides no way to validate a user’s input.
这时 WTForms 派上用场,它是一个灵活的表单呈现和验证库。Flask-WTF 扩展提供了一个与 WTForms 库简单的界面。
This is where WTForms, a flexible form, rendering and validation library comes handy. Flask-WTF extension provides a simple interface with this WTForms library.
使用 Flask-WTF ,我们可以在 Python 脚本中定义表单字段,并使用 HTML 模板呈现它们。还可以对 WTF 字段应用验证。
Using Flask-WTF, we can define the form fields in our Python script and render them using an HTML template. It is also possible to apply validation to the WTF field.
让我们看看此 HTML 的动态生成是如何运作的。
Let us see how this dynamic generation of HTML works.
首先,需要安装 Flask-WTF 扩展。
First, Flask-WTF extension needs to be installed.
pip install flask-WTF
安装的包包含一个 Form 类,必须将其用作用户定义表单的父元素。
The installed package contains a Form class, which has to be used as a parent for user- defined form.
WTforms 包含各种表单字段的定义。一些 Standard form fields 如下。
WTforms package contains definitions of various form fields. Some Standard form fields are listed below.
Sr.No |
Standard Form Fields & Description |
1 |
TextField Represents <input type = 'text'> HTML form element |
2 |
BooleanField Represents <input type = 'checkbox'> HTML form element |
3 |
DecimalField Textfield for displaying number with decimals |
4 |
IntegerField TextField for displaying integer |
5 |
RadioField Represents <input type = 'radio'> HTML form element |
6 |
SelectField Represents select form element |
7 |
TextAreaField Represents <testarea> html form element |
8 |
PasswordField Represents <input type = 'password'> HTML form element |
9 |
SubmitField Represents <input type = 'submit'> form element |
例如,一个包含文本字段的表单可以设计如下 −
For example, a form containing a text field can be designed as below −
from flask_wtf import Form
from wtforms import TextField
class ContactForm(Form):
name = TextField("Name Of Student")
除了 ‘name’ 字段,还自动创建 CSRF 令牌的隐藏字段。这是为了防止 Cross Site Request Forgery 攻击。
In addition to the ‘name’ field, a hidden field for CSRF token is created automatically. This is to prevent Cross Site Request Forgery attack.
渲染时,这将生成如下所示的等效 HTML 脚本。
When rendered, this will result into an equivalent HTML script as shown below.
<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 应用程序中使用了用户定义的表单类,并且表单使用模板渲染。
A user-defined form class is used in a Flask application and the form is rendered using a template.
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 包还包含验证器类。它可用于对表单字段应用验证。以下列表显示了常用的验证器。
WTForms package also contains validator class. It is useful in applying validation to form fields. Following list shows commonly used validators.
Sr.No |
Validators Class & Description |
1 |
DataRequired Checks whether input field is empty |
2 |
Email Checks whether text in the field follows email ID conventions |
3 |
IPAddress Validates IP address in input field |
4 |
Length Verifies if length of string in input field is in given range |
5 |
NumberRange Validates a number in input field within given range |
6 |
URL Validates URL entered in input field |
现在,我们将在联系表单的 name 字段中应用 ‘DataRequired’ 验证规则。
We shall now apply ‘DataRequired’ validation rule for the name field in contact form.
name = TextField("Name Of Student",[validators.Required("Please enter your name.")])
表单对象的 validate() 函数验证表单数据,如果验证失败则抛出验证错误。将 Error 消息发送到模板。在HTML模板中,错误消息会动态呈现。
The validate() function of form object validates the form data and throws the validation errors if validation fails. The Error messages are sent to the template. In the HTML template, error messages are rendered dynamically.
{% for message in form.name.errors %}
{{ message }}
{% endfor %}
以下示例 демонстрирует介绍的概念。 Contact form 的设计如下 (forms.py) 所示。
The following example demonstrates the concepts given above. The design of Contact form is given below (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 字段。
Validators are applied to the Name and Email fields.
以下是Flask应用程序脚本 (formexample.py) 。
Given below is the Flask application script (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) 如下 −
The Script of the template (contact.html) is as follows −
<!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 表单将按如下所示显示。
Run formexample.py in Python shell and visit URL http://localhost:5000/contact. The Contact form will be displayed as shown below.
如果有任何错误,页面将如下所示 −
If there are any errors, the page will look like this −
如果没有错误,将呈现 ‘success.html’ 。
If there are no errors, ‘success.html’ will be rendered.
Flask – SQLite
Python对 SQlite 有内置支持。Python发行版附带了SQlite3模块。有关在Python中使用SQLite数据库的详细教程,请参阅 this link 。在本节中,我们将看到Flask应用程序如何与SQLite交互。
Python has an in-built support for SQlite. SQlite3 module is shipped with Python distribution. For a detailed tutorial on using SQLite database in Python, please refer to this link. In this section we shall see how a Flask application interacts with SQLite.
创建SQLite数据库 ‘database.db’ 并在其中创建一个学生的表。
Create an SQLite database ‘database.db’ and create a students’ table in it.
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 函数。
Our Flask application has three View functions.
第一个 new_student() 函数绑定到URL规则 (‘/addnew’) 。它呈现一个包含学生信息表单的HTML文件。
First new_student() function is bound to the URL rule (‘/addnew’). It renders an HTML file containing student information form.
@app.route('/enternew')
def new_student():
return render_template('student.html')
‘student.html’ 的HTML脚本如下 −
The HTML script for ‘student.html’ is as follows −
<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。
As it can be seen, form data is posted to the ‘/addrec’ URL which binds the addrec() function.
此 addrec() 函数通过 POST 方法检索表单数据并插入 students 表中。插入操作成功或失败的对应消息呈现在 ‘result.html’ 上。
This addrec() function retrieves the form’s data by POST method and inserts in students table. Message corresponding to success or error in insert operation is rendered to ‘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 操作的结果。
The HTML script of result.html contains an escaping statement {{msg}} that displays the result of Insert operation.
<!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 对象,其中包含 students 表中的所有记录。该对象传递给 list.html 模板。
The application contains another list() function represented by ‘/list’ URL. It populates ‘rows’ as a MultiDict object containing all records in the students table. This object is passed to the list.html template.
@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 表中呈现数据。
This list.html is a template, which iterates over the row set and renders the data in an HTML table.
<!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’ ,作为应用程序的入口点。
Finally, the ‘/’ URL rule renders a ‘home.html’ which acts as the entry point of the application.
@app.route('/')
def home():
return render_template('home.html')
以下为 Flask-SQLite 应用程序的完整代码。
Here is the complete code of Flask-SQLite application.
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/ ,它会显示类似这样的简单菜单 -
Run this script from Python shell and as the development server starts running. Visit http://localhost:5000/ in browser which displays a simple menu like this −
点击 ‘Add New Record’ 链接以打开 Student Information 表单。
Click ‘Add New Record’ link to open the Student Information Form.
填写表单字段并提交。底层函数会将记录插入 students 表。
Fill the form fields and submit it. The underlying function inserts the record in the students table.
返回主页并点击 ‘Show List’ 链接。程序会显示包含示例数据的表格。
Go back to the home page and click ‘Show List’ link. The table showing the sample data will be displayed.
Flask – SQLAlchemy
在 Flask Web 应用中使用原始 SQL 在数据库上执行 CRUD 操作可能会很繁琐。相反, SQLAlchemy ,一个 Python 工具包是一个强大的 OR Mapper ,它为应用程序开发人员提供了 SQL 的全部功能和灵活性。Flask-SQLAlchemy 是 Flask 扩展,它为 Flask 应用程序添加了对 SQLAlchemy 的支持。
Using raw SQL in Flask web applications to perform CRUD operations on database can be tedious. Instead, SQLAlchemy, a Python toolkit is a powerful OR Mapper that gives application developers the full power and flexibility of SQL. Flask-SQLAlchemy is the Flask extension that adds support for SQLAlchemy to your Flask application.
使用原始 SQL 在数据库上执行 CRUD 操作可能会很繁琐。相反, SQLAlchemy ,一个 Python 工具包是一个强大的 OR Mapper ,它为应用程序开发人员提供了 SQL 的全部功能和灵活性。Flask-SQLAlchemy 是 Flask 扩展,它为 Flask 应用程序添加了对 SQLAlchemy 的支持。
What is ORM (Object Relation Mapping)?
大多数编程语言平台都是面向对象的。另一方面,RDBMS 服务器中的数据以表格的形式存储。对象关系映射是一种将对象参数映射到底层 RDBMS 表结构的技术。ORM API 提供了执行 CRUD 操作的方法,而无需编写原始 SQL 语句。
Most programming language platforms are object oriented. Data in RDBMS servers on the other hand is stored as tables. Object relation mapping is a technique of mapping object parameters to the underlying RDBMS table structure. An ORM API provides methods to perform CRUD operations without having to write raw SQL statements.
在本章中,我们将学习 Flask-SQLAlchemy 的 ORM 技术并构建一个小 Web 应用程序。
In this section, we are going to study the ORM techniques of Flask-SQLAlchemy and build a small web application.
Step 1 − 安装 Flask-SQLAlchemy 扩展。
Step 1 − Install Flask-SQLAlchemy extension.
pip install flask-sqlalchemy
Step 2 − 您需要从该模块导入 SQLAlchemy 类。
Step 2 − You need to import SQLAlchemy class from this module.
from flask_sqlalchemy import SQLAlchemy
Step 3 − 现在创建一个 Flask 应用程序对象,并将 URI 设置为要使用的数据库。
Step 3 − Now create a Flask application object and set URI for the database to be used.
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///students.sqlite3'
Step 4 − 然后创建一个 SQLAlchemy 类的对象,并将应用程序对象作为参数。该对象包含 ORM 操作的辅助函数。它还提供了一个父级 Model 类,用户定义的模型就是使用此类声明的。在下面的代码段中,创建了一个 students 模型。
Step 4 − Then create an object of SQLAlchemy class with application object as the parameter. This object contains helper functions for ORM operations. It also provides a parent Model class using which user defined models are declared. In the snippet below, a students model is created.
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() 方法。
Step 5 − To create / use database mentioned in URI, run the create_all() method.
db.create_all()
Session 对象 SQLAlchemy 管理 ORM 对象的所有持久性操作。
The Session object of SQLAlchemy manages all persistence operations of ORM object.
以下会话方法执行 CRUD 操作 −
The following session methods perform CRUD operations −
-
db.session.add(model object) − inserts a record into mapped table
-
db.session.delete(model object) − deletes record from table
-
model.query.all() − retrieves all records from table (corresponding to SELECT query).
您可以使用过滤器属性将过滤器应用于检索的记录集。例如,为了检索学生表中具有 city = ’Hyderabad’ 的记录,请使用以下语句 −
You can apply a filter to the retrieved record set by using the filter attribute. For instance, in order to retrieve records with city = ’Hyderabad’ in students table, use following statement −
Students.query.filter_by(city = ’Hyderabad’).all()
有了这么多的背景,现在我们应该为我们的应用程序提供视图函数,以便添加学生数据。
With this much of background, now we shall provide view functions for our application to add a student data.
应用程序的入口点是 show_all() 函数,绑定到 ‘/’ URL。学生表的记录集作为参数发送到 HTML 模板。模板中的服务器端代码在 HTML 表格形式中呈现记录。
The entry point of the application is show_all() function bound to ‘/’ URL. The Record set of students table is sent as parameter to the HTML template. The Server side code in the template renders the records in HTML table form.
@app.route('/')
def show_all():
return render_template('show_all.html', students = students.query.all() )
模板 (‘show_all.html’) 的 HTML 脚本如下 −
The HTML script of the template (‘show_all.html’) is like this −
<!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。
The above page contains a hyperlink to ‘/new’ URL mapping new() function. When clicked, it opens a Student Information form. The data is posted to the same URL in POST method.
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 时,表单数据被添加到学生表中,并且应用程序返回到主页,显示已添加的数据。
When the http method is detected as POST, the form data is added in the students table and the application returns to homepage showing the added data.
@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) 。
Given below is the complete code of application (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/ 。
Run the script from Python shell and enter http://localhost:5000/ in the browser.
单击 ‘Add Student’ 链接以打开 Student information 表单。
Click the ‘Add Student’ link to open Student information form.
填写并提交表单。主页将重新显示已提交的数据。
Fill the form and submit. The home page reappears with the submitted data.
我们可以看到如下所示的输出。
We can see the output as shown below.
Flask – Sijax
Sijax 代表 ‘Simple Ajax’ ,它是 Python/jQuery 库,旨在帮助您轻松地将 Ajax 引入到您的应用程序中。它使用 jQuery.ajax 发起 AJAX 请求。
Sijax stands for ‘Simple Ajax’ and it is a Python/jQuery library designed to help you easily bring Ajax to your application. It uses jQuery.ajax to make AJAX requests.
Configuration
-
SIJAX_STATIC_PATH − the static path where you want the Sijax javascript files to be mirrored. The default location is static/js/sijax. In this folder, sijax.js and json2.js files are kept.
-
SIJAX_JSON_URI − the URI to load the json2.js static file from
Sijax 使用 JSON 在浏览器和服务器之间传递数据。这意味着浏览器要么需要原生支持 JSON ,要么通过 json2.js 文件获取 JSON 支持。
Sijax uses JSON to pass the data between the browser and the server. This means that the browsers need either to support JSON natively or get JSON support from the json2.js file.
那样注册的函数无法提供 Sijax 功能,因为默认情况下无法通过 POST 方法访问它们(而 Sijax 使用 POST 请求)。
Functions registered that way cannot provide Sijax functionality, because they cannot be accessed using a POST method by default (and Sijax uses POST requests).
要使 View 函数能够处理 Sijax 请求,可通过 POST 使用 @app.route('/url', methods = ['GET', 'POST']) 访问它,或者像这样使用 @flask_sijax.route 帮助器装饰器 −
To make a View function capable of handling Sijax requests, make it accessible via POST using @app.route('/url', methods = ['GET', 'POST']) or use the @flask_sijax.route helper decorator like this −
@flask_sijax.route(app, '/hello')
每个 Sijax 处理程序函数(如这个)都会至少自动接收一个参数,就像 Python 将“self”传递给对象方法一样。 ‘obj_response’ 参数是函数向浏览器返回响应的一种方式。
Every Sijax handler function (like this one) receives at least one parameter automatically, much like Python passes ‘self’ to the object methods. The ‘obj_response’ parameter is the function’s way of talking back to the browser.
def say_hi(obj_response):
obj_response.alert('Hi there!')
当检测到 Sijax 请求时,Sijax 会像这样处理它 −
When Sijax request is detected, Sijax handles it like this −
g.sijax.register_callback('say_hi', say_hi)
return g.sijax.process_request()
Sijax Application
一个最小的 Sijax 应用程序代码如下 −
A minimal Sijax application code looks as follows −
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 处理该请求。
When a Sijax requests (a special jQuery.ajax() request) to the server, this request is detected on the server by g.sijax.is_sijax_request(), in which case you let Sijax handle the request.
使用 g.sijax.register_callback() 注册的所有函数都公开以便从浏览器调用。
All the functions registered using g.sijax.register_callback() are exposed for calling from the browser.
调用 g.sijax.process_request() 会指示 Sijax 执行适当的(先前注册的)函数并将响应返回至浏览器。
Calling g.sijax.process_request() tells Sijax to execute the appropriate (previously registered) function and return the response to the browser.
Flask – Deployment
Externally Visible Server
在开发服务器上只能在设置开发环境的计算机上访问 Flask 应用程序。这是一项默认行为,因为在调试模式下,用户可以在计算机上执行任意代码。
A Flask application on the development server is accessible only on the computer on which the development environment is set up. This is a default behavior, because in debugging mode, a user can execute arbitrary code on the computer.
如果禁用 debug ,可以通过将主机名设置为 ‘0.0.0.0’ ,使本地计算机上的开发服务器可供网络上的用户使用。
If debug is disabled, the development server on local computer can be made available to the users on network by setting the host name as ‘0.0.0.0’.
app.run(host = ’0.0.0.0’)
因此,您的操作系统将侦听到所有公共 IP。
Thereby, your operating system listens to all public IPs.
Deployment
要从开发环境切换到成熟的生产环境,应用程序需要部署在真正的 Web 服务器上。根据您的情况,可以使用不同的选项来部署 Flask Web 应用程序。
To switch over from a development environment to a full-fledged production environment, an application needs to be deployed on a real web server. Depending upon what you have, there are different options available to deploy a Flask web application.
对于小型应用程序,您可以考虑将它部署在以下任何托管平台上,所有这些平台都为小型应用程序提供免费计划。
For small application, you can consider deploying it on any of the following hosted platforms, all of which offer free plan for small application.
-
Heroku
-
dotcloud
-
webfaction
Flask 应用程序可以在这些云平台上部署。此外,也可以在 Google 云平台上部署 Flask 应用程序。Localtunnel 服务允许您在本地主机上共享您的应用程序,而无需更改 DNS 和防火墙设置。
Flask application can be deployed on these cloud platforms. In addition, it is possible to deploy Flask app on Google cloud platform. Localtunnel service allows you to share your application on localhost without messing with DNS and firewall settings.
如果您倾向于使用专用 Web 服务器来替代上述共享平台,则可以使用以下选项进行探索。
If you are inclined to use a dedicated web server in place of above mentioned shared platforms, following options are there to explore.
mod_wsgi
mod_wsgi 是一个 Apache 模块,为在 Apache 服务器上托管基于 Python 的 Web 应用程序提供了一个符合 WSGI 的接口。
mod_wsgi is an Apache module that provides a WSGI compliant interface for hosting Python based web applications on Apache server.
Installing mod_wsgi
要直接从 PyPi 安装官方版本,您可以运行 -
To install an official release direct from PyPi, you can run −
pip install mod_wsgi
要验证安装是否成功,请使用 start-server 命令运行 mod_wsgi-express 脚本 -
To verify that the installation was successful, run the mod_wsgi-express script with the start-server command −
mod_wsgi-express start-server
这将在端口 8000 上启动 Apache/mod_wsgi。然后,您可以通过将浏览器的指针指向 -
This will start up Apache/mod_wsgi on port 8000. You can then verify that the installation worked by pointing your browser at −
http://localhost:8000/
Creating .wsgi file
应该有一个 yourapplication.wsgi 文件。此文件包含在启动时执行的代码 mod_wsgi, 以获取应用程序对象。对于大多数应用程序,以下文件应该足够 -
There should be a yourapplication.wsgi file. This file contains the code mod_wsgi, which executes on startup to get the application object. For most applications, the following file should be sufficient −
from yourapplication import app as application
确保 yourapplication 和正在使用的所有库都位于 Python 加载路径上。
Make sure that yourapplication and all the libraries that are in use are on the python load path.
Flask – FastCGI
FastCGI 是适用于 nginix、lighttpd 和 Cherokee 等网络服务器的 Flask 应用程序的另一个部署选项。
FastCGI is another deployment option for Flask application on web servers like nginix, lighttpd, and Cherokee.
Configuring FastCGI
首先,您需要创建 FastCGI 服务器文件。让我们称之为 yourapplication.fcgi 。
First, you need to create the FastCGI server file. Let us call it yourapplication.fcgi.
from flup.server.fcgi import WSGIServer
from yourapplication import app
if __name__ == '__main__':
WSGIServer(app).run()
nginx 和更早版本的 lighttpd 需要一个套接字来明确地传递与 FastCGI 服务器进行通信。要做到这一点,您需要将套接字的路径传递给 WSGIServer 。
nginx and older versions of lighttpd need a socket to be explicitly passed to communicate with the FastCGI server. For that to work, you need to pass the path to the socket to the WSGIServer.
WSGIServer(application, bindAddress = '/path/to/fcgi.sock').run()
Configuring Apache
对于基本的 Apache 部署,您的 .fcgi 文件将出现在您的应用程序 URL 中,例如 example.com/yourapplication.fcgi/hello/ 。有几种方法可以配置您的应用程序,以便 yourapplication.fcgi 不出现在 URL 中。
For a basic Apache deployment, your .fcgi file will appear in your application URL e.g. example.com/yourapplication.fcgi/hello/. There are few ways to configure your application so that yourapplication.fcgi does not appear in the URL.
<VirtualHost *>
ServerName example.com
ScriptAlias / /path/to/yourapplication.fcgi/
</VirtualHost>
Configuring lighttpd
lighttpd 的基本配置如下所示 -
Basic configuration of lighttpd looks like this −
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 。
Remember to enable the FastCGI, alias and rewrite modules. This configuration binds the application to /yourapplication.