1. Initialisation
Dans ce chapitre, vous apprendrez les différentes parties de l'application Flask. En même temps, vous écrirez et exécuterez votre première application Web Flask.
Toutes les applications Flask doivent créer une instance d'application . Toutes les demandes reçues du client sont transmises à cet objet pour traitement à l'aide du protocole d'interface de passerelle de serveur Web. Cette instance d'application est un objet de la classe Flask, généralement créé à l'aide de la méthode suivante :
from flask import Flask app = Flask(__name__)
Le constructeur unique de la classe Flask Le paramètre requis est le module ou package principal de l'application. Pour la plupart des applications, la variable __name__ de Python est la valeur correcte que vous devez transmettre.
Remarque : pour les développeurs Flask, le paramètre name transmis au constructeur de l'application Flask peut prêter à confusion. Flask utilise ce paramètre pour déterminer le répertoire racine de l'application afin que les fichiers de ressources puissent être trouvés par rapport à ce chemin à l'avenir.
Plus tard, vous pourrez voir des initialisations d'instances d'application plus complexes, mais pour les applications simples, celles-ci sont suffisantes.
2. Fonctions de routage et d'affichage
Les clients tels que les navigateurs Web envoient des requêtes au service Web, puis les envoient à l'instance d'application Flask. L'instance d'application doit savoir quel code doit être exécuté pour chaque requête d'URL. Elle configure donc un mappage d'URL vers la fonction Python. Ces opérations qui établissent des connexions entre les URL et les fonctions sont appelées routage .
Le moyen le plus pratique de définir des routes dans une application Flask est d'enregistrer la fonction décorée en tant que route en définissant explicitement le décorateur app.route sur l'instance d'application. L'exemple suivant montre comment utiliser des décorateurs pour déclarer un itinéraire :
@app.route('/') def index(): return '<h1>Hello World!</h1>'
Remarque : les décorateurs sont un standard dans le langage Python. Propriétés ils peuvent modifier le comportement d'une fonction de différentes manières. Un modèle courant consiste à utiliser un décorateur pour enregistrer une fonction en tant que gestionnaire d'événements.
Dans l'exemple précédent, enregistrez la fonction index() en tant que gestionnaire d'événements pour l'URL racine de l'application. Si cette application est déployée sur le serveur et liée au nom de domaine www.example.com, alors saisir http://www.php.cn/ dans la barre d'adresse de votre navigateur déclenchera index() pour exécuter le service. La valeur de retour de cette fonction reçue par le client est appelée réponse . Si le client est un navigateur Web, la réponse est le document affiché à l'utilisateur.
Les fonctions similaires à index() sont appelées fonctions d'affichage. La réponse renvoyée par la vue peut être une simple chaîne de contenu HTML, mais elle peut également prendre une forme plus complexe, comme vous le verrez.
Remarque : la chaîne de réponse est intégrée dans le code Python, ce qui rend le code difficile à contrôler. Ici, nous introduisons uniquement le concept de réponse. Vous apprendrez la bonne façon de générer des réponses au chapitre 3.
Si vous remarquez comment sont formées certaines des URL de sites Web que vous utilisez quotidiennement, vous constaterez qu'il existe des variables dans beaucoup d'entre elles. Par exemple, l'URL de votre page de profil Facebook est http://www.php.cn/;username> , votre nom d'utilisateur en fait donc partie. Flask prend en charge ces types d'URL en utilisant une syntaxe spéciale dans les décorateurs de routes. L'exemple suivant définit un itinéraire avec un composant nommé dynamiquement :
@app.route('/user/<name>') def user(name): return '<h1>Hello, %s!</h1>' % name
La partie entre crochets est une section dynamique, donc toutes les URL correspondant à la section statique seront mappées sur cette route. Lorsque la fonction d'affichage est appelée, Flask envoie le composant dynamique en paramètre. Dans la fonction de visualisation de l'exemple précédent, ce paramètre est utilisé pour générer un message d'accueil personnalisé en réponse.
Les composants dynamiques du routage sont par défaut des chaînes, mais peuvent être définis comme d'autres types. Par exemple, la route /user/
3. Démarrage du service
L'instance d'application dispose d'une méthode d'exécution pour démarrer le service Web intégré à Flask :
if __name__ == '__main__': app.run(debug=True)
__name__ == '__main__' est utilisé ici pour garantir que le service Web a été démarré lorsque le script est exécuté immédiatement. Lorsqu'un script est importé par un autre script, il est traité comme le script parent et démarrera un service différent, donc l'appel app.run() sera ignoré.
Une fois le service démarré, il entrera dans une boucle en attendant les demandes et les servira. Cette boucle continue jusqu'à ce que l'application soit arrêtée, par exemple en appuyant sur Ctrl-C.
Il existe plusieurs paramètres d'option pour app.run() pour configurer le mode de fonctionnement du service Web. Pendant le développement, vous pouvez facilement activer le mode débogage, qui activera le débogueur et le rechargement. Cela se fait en passant le débogage comme True.
Remarque : Les services Web fournis par Flask ne sont pas utilisés dans des environnements de production. Vous découvrirez les services Web dans les environnements de production au chapitre 17.
4. Une application complète
Dans la section précédente, vous avez découvert les différentes parties d'une application Web Flask, il est maintenant temps d'en écrire une. L'intégralité du script de l'application hello.py combine simplement les trois parties décrites précédemment en un seul fichier. L'exemple d'application 2-1 est présenté.
Exemple hello.py : une application Flask complète
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Hello World!
' if __name__ == '__main__': app.run(debug=True)
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 2a来切换到这个版本的应用程序。
运行应用程序之前,请确保你在之前创建的虚拟环境已经是激活状态且已安装Flask。现在打开你的web浏览器并在地址栏输入 http://www.php.cn/:5000/ 。下图显示连接到应用程序后的web浏览器。
然后输入以下命令启动应用程序:
(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__ == '__main__': app.run(debug=True)
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 2b来切换到这个版本的应用程序。
测试动态路由,确保服务正在运行随后访问 http://localhost:5000/user/Dave 。生成的应用程序会使用动态参数名响应一个定制的问候。尝试不同的名称,看看视图函数总是生成响应基于给定的名称。
5.1、应用程序Context和请求Context
当Flask从客户端收到一个请求,它需要提供几个可用对象给视图函数处理。request对象是个不错的例子,它封装了客户端发送的HTTP请求。
Flask视图函数访问request对象的最好方式,就是作为一个参数发送它,但这需要每个单一视图函数在应用程序中有一个额外的参数。考虑一下,如果request对象不是唯一一个视图函数需要访问完成请求的对象,事情将会变得更加复杂。
为了避免弄乱视图函数那些可能需要或不需要的参数,Flask使用context来临时确定可访问的全局对象。也多亏了context,视图函数可以写成下面这样:
from flask import request @app.route('/') def index(): user_agent = request.headers.get('User-Agent') return ' <p>Your browser is %s</p> ' % user_agent
注意,在这个视图函数中,request是如何被作为一个全局变量来使用的。现实中,request是不能作为全局变量的,如果是多线程服务器,同一时间线程作用于不同客户端的不同请求,所以每一个线程需要看到request中的不同对象。contexts使得Flask确定可访问的全局变量而不干扰其他线程。
注:线程是可以独立管理的最小指令序列。一个进程中有多个活动的线程是非常常见的,有时分享内存或文件句柄资源。多线程web服务器会启动一个线程池并从池中选择一个线程来处理每个传入的请求。
Flask有两类context:应用级context 和 请求级context。表2-1展示了这些context提供的变量。
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 'hello' >>> 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 '/' (HEAD, OPTIONS, GET) -> index>, <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>, <Rule '/user/<name>' (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('/') def index(): return '<h1>Bad Request</h1>', 400
视图函数返回的响应还可以携带第三个参数,添加一个头部字典给HTTP响应。通常很少用到,但是你可以在第十四章看到示例。
除了返回一个、两个或三个值的元组,Flask视图函数可以选择返回response对象。make_response()函数可携带一个、两个或三个参数,和视图函数返回的值一样,并返回一个response对象。有时候在视图函数中执行这个转换是非常有用的,然后使用response对象中的方法进一步配置响应。下面的示例创建response对象并设置cookie:
from flask import make_response @app.route('/') def index(): response = make_response(' <h1>This document carries a cookie!</h1> ') response.set_cookie('answer', '42') return response
有一类特殊的响应称作重定向。这类响应不包含页面文档;只是给浏览器一个新的URL去加载新的页面。重定向通常和web表单一起使用,你将在第四章学习。
重定向通常由302响应状态码注明并且重定向的URL由头部的Location给出。重定向响应可以使用三个值的返回生成,也可通过响应对象生成,但是鉴于它频繁的使用,Flask提供redirect()函数来创建这样的响应:
from flask import redirect @app.route('/') def index(): return redirect('http://www.example.com')
另一个具有中断功能的特殊响应用来错误处理。下面的示例,当URL给出的id动态参数不是一个合法的用户时返回状态码404:
from flask import abort @app.route('/user/<id>') def get_user(id): user = load_user(id) if not user: abort(404) return ' <h1>Hello, %s</h1> ' % 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__ == '__main__': 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地址。
更多用Utilisez le framework Flask de Python pour créer votre première application Web相关文章请关注PHP中文网!