Home  >  Article  >  Backend Development  >  Use Python’s Flask framework to build your first web application

Use Python’s Flask framework to build your first web application

高洛峰
高洛峰Original
2017-03-03 15:30:253171browse

1. Initialization

In this chapter, you will learn the different parts of the Flask application. At the same time, you will write and run your first Flask web application.

All Flask applications must create an application instance. All requests received from the client are passed to this object for processing using the web server gateway interface protocol. This application instance is an object of the Flask class, usually created using the following method:


from flask import Flask
app = Flask(__name__)


The only thing required by the Flask class constructor The parameter is the main module or package of the application. For most applications, Python's __name__ variable is the correct value you need to pass.

Note: For Flask developers, the name parameter passed to the Flask application constructor can be confusing. Flask uses this parameter to determine the root directory of the application so that resource files can be found relative to this path in the future.
You can see more complex application instance initialization later, but for simple applications these are sufficient.

2. Routing and view functions
Clients such as web browsers send requests to the web service, and then send them to the Flask application instance. The application instance needs to know what code needs to be run for each URL request, so it sets up a map of URLs to the Python function. These operations that establish connections between URLs and functions are called routing.

The most convenient way to define routes in a Flask application is to register the decorated function as a route by explicitly defining the app.route decorator on the application instance. The following example demonstrates how to use decorators to declare a route:


@app.route('/')
def index():
 return &#39;<h1>Hello World!</h1>&#39;


Note: Decorators are a standard feature of the Python language; They can change the behavior of a function in different ways. A common pattern is to use a decorator to register a function as an event handler.
In the previous example, register the index() function as an event handler for the root URL of the application. If this application is deployed on the server and bound to the www.example.com domain name, then entering http://www.php.cn/ in your browser address bar will trigger index() to run the service. The return value of this function received by the client is called the response . If the client is a web browser, the response is the document displayed to the user.

Functions similar to index() are called view functions. The response returned by the view can be a simple string of HTML content, but it can also take a more complex form, as you will see.

Note: The response string is embedded in the Python code, making the code difficult to control. Here we only introduce the concept of response. You'll learn the correct way to generate responses in Chapter 3.
If you notice how some of the website URLs you use every day are formed, you will find that many have variables. For example, the URL of your Facebook profile page is http://www.php.cn/;username> , so your username is part of it. Flask supports these types of URLs using special syntax in route decorators. The following example defines a route with a dynamic name component:


@app.route(&#39;/user/<name>&#39;) 
def user(name):
 return &#39;<h1>Hello, %s!</h1>&#39; % name


The part enclosed in angle brackets is the dynamic part, So any URLs matching the static part will be mapped to this route. When the view function is called, Flask sends the dynamic component as a parameter. In the view function of the previous example, this parameter is used to generate a personalized greeting in response.

Dynamic components in routing default to strings, but can be defined as other types. For example, the route /user/ only matches URLs that have an integer in the id dynamic segment. Flask routing supports int, float and path. path is also a string type, but slashes are not considered delimiters, but are considered part of the dynamic component.

3. Service startup
The application instance has a run method for starting the Flask-integrated web service:


if __name__ == &#39;__main__&#39;:
 app.run(debug=True)


__name__ == '__main__' is used here to ensure that the web service has been started when the script is executed immediately. When a script is imported by another script, it is treated as the parent script and will start a different service, so the app.run() call will be skipped.

Once the service starts, it will enter a loop waiting for requests and serve them. This loop continues until the application is stopped, for example by pressing Ctrl-C.

There are several option parameters that can be used to configure the operating mode of the web service for app.run(). During development, you can easily turn on debug mode, which will activate debugger and reloader. This is done by passing debug as True.

Note: The web service provided by Flask is not used in production environments. You will learn about web services in production environments in Chapter 17.

4. A complete application
In the previous section, you learned about the different parts of a Flask web application, now it’s time to write one. The entire hello.py application script simply combines the three previously described parts into one file. Application example 2-1 is shown.

Example hello.py: A complete Flask application


from flask import Flask
app = Flask(__name__)

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

Hello World!

' if __name__ == &#39;__main__&#39;: app.run(debug=True)


建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 2a来切换到这个版本的应用程序。
运行应用程序之前,请确保你在之前创建的虚拟环境已经是激活状态且已安装Flask。现在打开你的web浏览器并在地址栏输入 http://www.php.cn/:5000/ 。下图显示连接到应用程序后的web浏览器。

Use Python’s Flask framework to build your first web application

然后输入以下命令启动应用程序:


(venv) $ python hello.py
  * Running on http://127.0.0.1:5000/
 * Restarting with reloader


如果你输入任何其他URL,应用程序将不知道如何操作它并且将返回错误代码404给浏览器——当你访问一个不存在的网页也会得到该错误。

下面所示应用程序的增强版添加了第二个动态路由。当你访问这个URI,你应该可以看到一个个性的问候。

示例hello.py:带有动态路由的Flask应用程序


from flask import Flask
app = Flask(__name__)

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

Hello World!

' @app.route('/user/') def user(name): return '

Hello, %s!

' % name if __name__ == &#39;__main__&#39;: app.run(debug=True)


建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 2b来切换到这个版本的应用程序。
测试动态路由,确保服务正在运行随后访问 http://localhost:5000/user/Dave  。生成的应用程序会使用动态参数名响应一个定制的问候。尝试不同的名称,看看视图函数总是生成响应基于给定的名称。

Use Python’s Flask framework to build your first web application


5.1、应用程序Context和请求Context

当Flask从客户端收到一个请求,它需要提供几个可用对象给视图函数处理。request对象是个不错的例子,它封装了客户端发送的HTTP请求。

Flask视图函数访问request对象的最好方式,就是作为一个参数发送它,但这需要每个单一视图函数在应用程序中有一个额外的参数。考虑一下,如果request对象不是唯一一个视图函数需要访问完成请求的对象,事情将会变得更加复杂。

为了避免弄乱视图函数那些可能需要或不需要的参数,Flask使用context来临时确定可访问的全局对象。也多亏了context,视图函数可以写成下面这样:


from flask import request

@app.route(&#39;/&#39;)
def index():
 user_agent = request.headers.get(&#39;User-Agent&#39;)
 return &#39;

<p>Your browser is %s</p>

&#39; % user_agent


注意,在这个视图函数中,request是如何被作为一个全局变量来使用的。现实中,request是不能作为全局变量的,如果是多线程服务器,同一时间线程作用于不同客户端的不同请求,所以每一个线程需要看到request中的不同对象。contexts使得Flask确定可访问的全局变量而不干扰其他线程。

注:线程是可以独立管理的最小指令序列。一个进程中有多个活动的线程是非常常见的,有时分享内存或文件句柄资源。多线程web服务器会启动一个线程池并从池中选择一个线程来处理每个传入的请求。
Flask有两类context:应用级context 和 请求级context。表2-1展示了这些context提供的变量。

Use Python’s Flask framework to build your first web application


Flask激活(或压栈)应用级context和请求级context在调度请求之前,然后删除他们当请求被处理后。当应用程序context被压入栈,线程中current_app和g变量变得可用;同样的,当请求级context被压入栈,request和session变量也同样变得可用。如果这些变量中的任何一个不是由激活的应用级或请求级context访问,会产生错误。在后面的章节会详细讨论四个context变量,所以不要担心你不理解它们的用处。

下面的Python shell会话演示了应用级context是如何工作的:


>>> from hello import app
>>> from flask import current_app
>>> current_app.name
Traceback (most recent call last):
...
RuntimeError: working outside of the application context
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>> current_app.name
&#39;hello&#39;
>>> app_ctx.pop()


在这个示例中,当应用级context没有激活,但是却作为有效的context被压入栈中,current_app.name报错。注意在应用程序实例中一个应用级context是如何通过调用app.app_context()来获得的。

5.2、请求调度

当一个应用程序收到客户端的请求,它需要找到响应的视图函数为之服务。对于这个任务,Flask会在应用程序的URL映射中查找请求的URL,该映射包含URLs和操作它们的视图函数。Flask通过app.route装饰器或非装饰器版本app.add_url_rule()来建立这个映射。

看一下Flask应用程序中URL映射是怎样的,你可以在Python shell中检查hello.py创建的映射。测试中,请确保你的虚拟环境是激活状态:


(venv) % python
>>> from hello import app
>>> app.url_map
Map([<Rule &#39;/&#39; (HEAD, OPTIONS, GET) -> index>,
 <Rule &#39;/static/<filename>&#39; (HEAD, OPTIONS, GET) -> static>,
 <Rule &#39;/user/<name>&#39; (HEAD, OPTIONS, GET) -> user>])


URL映射中所示的HEAD、OPTIONS、GET元素为request方法,由路由处理。Flask连接方法到每个路由,这样不同的请求方法发送到相同的URL可以被不同的视图函数处理。HEAD和OPTIONS方法由Flask自动管理,所以实际上可以说,在这个应用程序中URL映射的三个路由都连接到GET方法了。在第四章你将学习为路由指定不同的请求方法。

5.3、请求Hooks

有些时候在每个请求处理之前或之后执行代码是非常有用的。例如,在开始每一个请求前可能有必要创建数据库连接,或对用户请求进行验证。为了避免复制处理这些操作的代码到每一个视图函数中,Flask给你选择注册相同函数来调用,在请求被分配给视图函数之前或之后。

请求hooks由装饰器实现。下面是四个Flask支持的hooks:

(1)before_first_request:在第一个请求被处理前注册一个函数运行。
(2)before_request:在每一个请求前注册一个函数运行。
(3)after_request:如果没有未处理的异常发生,在每一个请求后注册一个函数运行。
(4)teardown_request:即使未处理的异常发生,在每一个请求后注册一个函数运行。
在请求hook函数和视图函数之间共享数据的惯用方法就是使用g全局context。例如,before_request处理程序可以从数据库加载已登录的用户并保存在g.user中。之后,当视图函数被调用,可以从那访问用户。

请求hooks的示例会在未来的章节中展示给大家,所以不用担心,

5.4、响应

当Flask调用一个视图函数,并期望它的返回值去响应该请求。大多数的响应是将简单字符串构成的HTML页面发回给客户端。

但是HTTP协议需要比字符串更多的信息作为请求的响应。一个HTTP响应中非常重要的部分是状态码,Flask默认设置200来指示请求已经成功处理。

当视图函数需要用不同的状态码响应,可以在响应文本后添加数字码作为第二个返回值。例如,下面的视图函数返回400错误状态码的请求:


@app.route(&#39;/&#39;)
def index():
 return &#39;<h1>Bad Request</h1>&#39;, 400


视图函数返回的响应还可以携带第三个参数,添加一个头部字典给HTTP响应。通常很少用到,但是你可以在第十四章看到示例。

除了返回一个、两个或三个值的元组,Flask视图函数可以选择返回response对象。make_response()函数可携带一个、两个或三个参数,和视图函数返回的值一样,并返回一个response对象。有时候在视图函数中执行这个转换是非常有用的,然后使用response对象中的方法进一步配置响应。下面的示例创建response对象并设置cookie:


from flask import make_response

@app.route(&#39;/&#39;)
def index():
 response = make_response(&#39;

<h1>This document carries a cookie!</h1>

&#39;)
 response.set_cookie(&#39;answer&#39;, &#39;42&#39;)
 return response


有一类特殊的响应称作重定向。这类响应不包含页面文档;只是给浏览器一个新的URL去加载新的页面。重定向通常和web表单一起使用,你将在第四章学习。

重定向通常由302响应状态码注明并且重定向的URL由头部的Location给出。重定向响应可以使用三个值的返回生成,也可通过响应对象生成,但是鉴于它频繁的使用,Flask提供redirect()函数来创建这样的响应:


from flask import redirect

@app.route(&#39;/&#39;)
def index():
 return redirect(&#39;http://www.example.com&#39;)


另一个具有中断功能的特殊响应用来错误处理。下面的示例,当URL给出的id动态参数不是一个合法的用户时返回状态码404:


from flask import abort

@app.route(&#39;/user/<id>&#39;)
def get_user(id):
 user = load_user(id)
 if not user:
  abort(404)
 return &#39;

<h1>Hello, %s</h1>

&#39; % user.name


注意终止不是指将控制权返回给调用它的函数,而是指通过抛出异常将控制权返回给web服务。

6、Flask扩展
Flask是可扩展的。它故意腾出地给重要的功能,例如数据库和用户授权,给你自由去选择最适合你的应用程序的包,或写一个自己想要的。

社区开发了非常多的扩展用于各种用途,如果这还不够,可以使用任何Python标准包和库。为了让你了解一个扩展是如何并入一个应用程序的,下面的章节给hello.py添加一个扩展,增加应用程序的命令行参数。

6.1、Flask-Script命令行选项

Flask开发,其web服务器支持一系列的启动配置选项,但是配置它们的唯一方式只有在脚本中传递参数给app.run()并调用。这不是非常的方便,理想方法是通过命令行参数传递配置选项。

Flask-Script是给你的Flask应用程序添加命令行解释的扩展。它打包了一组通用的选项,还支持自定义命令。

使用pip安装扩展:


(venv) $ pip install flask-script


下面展示了在 hello.py 应用程序中添加命令行解释的变化。
示例. hello.py:使用Flask-Script


from flask.ext.script import Manager

manager = Manager(app)

# ...

if __name__ == &#39;__main__&#39;:
 manager.run()


专为Flask开发的扩展暴露在flask.ext命名空间下。Flask-Script从flask.ext.script中导出一个名为Manager的类。

初始化这个扩展的方法和其他许多扩展一样:主类实例的初始化是通过将应用程序实例作为参数传递给构造函数实现的。创建的对象适当的用于每一个扩展。在这个示例中,服务器启动通过manager.run()来路由,且命令行在这被解析。

建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 2c来切换到这个版本的应用程序。
因为这些变化,应用程序获得一组基本的命令行选项。运行hello.py显示可用信息:


$ python hello.py



usage: hello.py [-h] {shell, runserver} ...

positional arguments:
 {shell, runserver}
 shell   在Flask应用程序上下文的内部运行一个Python Shell。
 runserver  运行Flask开发服务器,例如:app.run()

optional arguments:
 -h, --help  显示这个帮助信息并退出


shell命令用于在应用程序上下文中启动一个Python shell会话。你可以使用这个会话去运行维护任务,或测试,或调试错误。

runserver命令,就像它的名称一样,启动web服务。运行python hello.py runserver在调试模式下启动web服务,还有更多的选项:


(venv) $ python hello.py runserver --help
usage: hello.py runserver [-h] [-t HOST] [-p PORT] [--threaded]
       [--processes PROCESSES] [--passthrough-errors] [-d]
       [-r]


运行Flask开发服务器,例如:app.run()


optional arguments:
 -h, --help    显示这个帮助信息并退出
 -t HOST, --host HOST
 -p PORT, --port PORT
 --threaded
 --processes PROCESSES
 --passthrough-errors
 -d, --no-debug
 -r, --no-reload


--host参数是一个非常有用的选项,因为它能告诉web服务器监听哪个网络接口的客户端连接。默认,Flask开发的web服务器监听localhost的连接,所以只有来自内部计算机运行的服务器可以接收。下面的命令使得web服务器监听公网接口,其他网络上的计算机可以连接:


(venv) $ python hello.py runserver --host 0.0.0.0
 * Running on http://0.0.0.0:5000/
 * Restarting with reload


现在web服务器应该可以从网络中的任何一台计算机访问 http://a.b.c.d:5000 ,“a.b.c.d”是运行服务的计算机的外部IP地址。

更多用Use Python’s Flask framework to build your first web application相关文章请关注PHP中文网!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn