摘要:局部变量用于保存从表单中接收到的名字,初始化时变量为。在语句中,这个名字被赋值给局部变量且表单域的数据属性通过赋值为空字符串而被清除。示例重定向和用户会话在上一个版本中,局部变量用于保存用户在表单中输入的姓名。
4、视图函数中的表单操作
在新版本的hello.py中,index()视图函数渲染表单并接收其数据。示例4-4展示更新后的index()视图函数。
示例4-4. hello.py:路由方法
@app.route("/", methods=["GET", "POST"]) def index(): name = None form = NameForm() if form.validate_on_submit(): name = form.name.data form.name.data = "" return render_template("index.html", form=form, name=name)
methods参数被添加到app.route装饰器中,目的是让Flask注册视图函数为GET和POST请求处理程序到URL映射中。若methods参数未给出,视图函数将只注册为GET请求。
添加POST到方法列表中是有必要的,因为表单提交使用POST请求操作会更方便。使用GET请求提交表单也行,只是GET请求没有body部分,数据是追加到URL上作为返回字符串且可以在浏览器的地址栏中看到。由于这个和其他一些原因,表单提交通常使用POST请求。
局部变量name用于保存从表单中接收到的名字,初始化时变量为None。视图函数创建一个NameForm实例来表示一个表单。表单的validate_on_submit()方法会在表单被提交且数据通过了所有验证的时候返回True。其他情况下validate_on_submit()返回False。该方法的返回值有效的决定了表单是需要渲染还是其他处理。
当用户第一次访问应用程序,服务器会收到一个没有表单数据的GET请求,这个时候validate_on_submit()会返回False。if语句中的代码将被略过直接进行渲染模板处理,这个时候render_template()函数将获取表单对象和已经被设置为None的name变量作为参数。用户则可以在浏览器上看到表单的显示。
当用户提交表单,服务器会收到一个带有数据的POST请求。validate_on_submit()调用Required()验证程序验证相应的表单域。如果name不为空,验证程序接收它同时validate_on_submit()返回True。现在用户输入的名字已经是作为表单域可访问的数据属性。在if语句中,这个名字被赋值给局部变量name且表单域的数据属性通过赋值为空字符串而被清除。调用最后一行的render_template()来渲染模板,但是这次name参数包含了来自表单的名字,所以可以看到一个个性化的打招呼页面。
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 4a来切换到这个版本的应用程序。
图像4-1展示用户初次进入网站在浏览器窗口看到的表单是怎样的。当用户提交名字,应用程序收到一个个性化的打招呼响应。下面的表单仍然出现,所以只要愿意用户可以提交一个新的名字。图像4-2展示用户输入名字后的状态。
图像4-1. Flask-WTF的web表单
如果用户提交一个空名字的表单,Required()验证程序捕捉到错误,就像图像4-3那样。注意这些功能都是自动提供的。这是一个很好的例子,精心设计的Flask-WTF和Flask-Bootstrap扩展能让您的应用程序更强大。
图像4-2. 提交后的web表单
图像4-3. 验证错误后的web表单
5、重定向和用户sessions上个版本的hello.py有个问题。如果你输入你的名字并提交它,然后单击浏览器中刷新按钮,你将得到一个警告要求再次确认之前提交的表单。因为请求刷新页面的时候浏览器重复了上一次发送的请求。当上一次发送的是一个带有表单数据的POST请求,刷新页面会导致重复的表单提交,事实上这些并不是我们想看到的。
许多用户不能理解来自浏览器的这些警告。出于这个原因,对web应用程序来说,一种不错的方法是永远不将POST请求作为浏览器最后发送的请求。
这个方法可以使用redirect响应POST请求来代替常规的响应来实现。重定向是一个特殊类型的响应,使用URL来代替HTML代码字符串。当浏览器收到这个响应,它就会给重定向URL发出一个GET请求,然后显示页面。页面也许需要几毫秒的时间来加载,因为需要发送第二个请求给服务器,除此之外用户不会看到任何不同。现在最后一次请求为GET,所以刷新会像预期的那样。这个方法被称为Post/Redirect/Get模式。
但是这个方法带来了第二个问题。当应用程序处理POST请求,需要访问用户输入并保存在form.name.data中的名字,但是一旦该请求结束表单数据就会丢失。因为POST请求是通过重定向来处理,应用程序需要存储名字,以便重定向后的请求可以得到它并使用它来创建真实的响应。
应用程序可以“记住”一些变量从一个请求到另一个请求通过将变量保存到用户会话中,对于每一个连接过来的客户端它都是一个私有存储区域。作为一个与请求上下文关联的变量之一,用户会话已经在第二章中介绍过了。它被称为会话并可以像Python标准字典那样访问。
注:默认情况下,用户会话被存放于客户端的cookies,使用配置的SECRET_KEY来加密签名。任何篡改cookie内容将会使签名无效,从而使会话失效。
示例4-5展示实现重定向和用户会话的index()视图函数。
示例4-5. hello.py:重定向和用户会话
from flask import Flask, render_template, session, redirect, url_for @app.route("/", methods=["GET", "POST"]) def index(): form = NameForm() if form.validate_on_submit(): session["name"] = form.name.data return redirect(url_for("index")) return render_template("index.html", form=form, name=session.get("name"))
在上一个版本中,局部变量name用于保存用户在表单中输入的姓名。这个变量位于用户会话中的session["name"]中,因此可以保存很长时间。
现在请求来自表单的合法数据都会以redirect()调用来结束,生成HTTP重定向响应。redirect()函数把URL作为重定向的参数。这个例子中使用的重定向URL是一个根URL,所以响应可以写成redirect("/")这样简洁,但是我们通常使用Flask的URL生成器函数url_for()来代替。我们鼓励使用url_for()函数来生成URLs,因为该函数使用URL映射来生成URLs,所以生成的URLs保证与定义的路由兼容,并且使用这个函数任何路由名发生变化都会自动变得有效,路由功能不受影响。
url_for()唯一必须的参数就是endpoint名,也是每个路由的内部名。默认情况下,路由的endpoint是一个附加到视图函数的名称。在这个示例中,处理根URL的视图函数为index(),所以给url_for()的名称为index。
最后一个改动是在render_template()函数中,使用session.get("name")从会话中获取name参数。和使用普通字典一样,使用get()去请求字典key来避免发生找不到key异常,因为对于没有的keyget()返回默认值None。
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 4b来切换到这个版本的应用程序。
这个版本的应用程序,你可以在你的浏览器中刷新页面看到你预期的行为。
6、消息提示有时候在请求完成后给用户一个提示消息是非常有用的。可以是一个确认消息、警告消息或错误消息。典型的示例就是当你在网站提交登录表单出现错误的时候服务器响应渲染登录表单并伴随一条消息,告知你的用户名或密码无效。
作为核心特性Flask具有这样的功能。示例4-6展示如何使用flash()函数来实现这一目的。
示例4-6. hello.py:消息提示
from flask import Flask, render_template, session, redirect, url_for, flash @app.route("/", methods=["GET", "POST"]) def index(): form = NameForm() if form.validate_on_submit(): old_name = session.get("name") if old_name is not None and old_name != form.name.data: flash("Looks like you have changed your name!") session["name"] = form.name.data form.name.data = "" return redirect(url_for("index")) return render_template("index.html", form = form, name = session.get("name"))
在这个示例中,每次提交一个名字都会和用户会话中保存的名字进行比较。如果两个名字不一样,flash()函数会被调用,消息会在下一次发回客户端的响应中显示。
调用flash()还不能获取并显示消息;应用程序使用的模板需要渲染这些消息。渲染消息最好的地方是在基础模板中,因为这可以使得所有页面都可以使用这些消息。Flask提供get_flashed_messages()函数给模板去接收消息并渲染它们,就像4-7展示的那样。
示例4-7. templates/base.html:消息渲染
{% block content %}{% for message in get_flashed_messages() %}{% endblock %}{{ message }}{% endfor %} {% block page_content %}{% endblock %}
在这个示例中,使用Bootstrap的警告CSS样式做警告消息渲染(展示在图像4-4中就是之一)。
图像4-4. 消息提示
这里需要使用循环因为可能会有多个消息排队显示,在前面的请求周期中每次都会调用flash()。
从get_flashed_messages()中检索到的消息在下次调用这个函数时是不会返回的。所以消息只显示一次然后丢弃。
建议:如果你有克隆在GitHub上的应用程序,你现在可以运行git checkout 4c来切换到这个版本的应用程序。
能够接收用户通过web表单发送的数据是大多数应用程序的基本功能,同样将数据到永久存储到媒介上也是必须的。下一章的主题是Flask和数据库的使用。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/37475.html
摘要:每个表单域都可以连接到一个或多个是一个用于检查用户提交的输入是否合法的函数。表单域构造函数的第一个参数是一个,在渲染表单到时会使用。验证确保提交的表单域不为空。表单域验证都是直接从包中导入。表格展示了一组支持的标准表单域。 第二章中介绍的request对象公开了所有客户端发送的请求信息。特别是request.form可以访问POST请求提交的表单数据。 尽管Flask的request...
摘要:用真实的值替换变量并返回最终响应字符串,这个过程称为渲染。示例展示模板实现该响应。控制结构提供一些控制结构用于改变模板流。这个示例展示如何使用循环做到这些同样支持宏,这和代码中的函数很像。 写代码最关键的是要易于维护且结构清晰整洁。目前为止,你看到的例子都过于简单从而没有做这方面的要求。Flask视图函数希望将两个应该完全独立的任务一并处理,两个任务有两种代码,一并处理势必会引发问题。...
摘要:如果路由重组,模板中的链接将被打断而变得无法访问。静态文件应用程序不仅仅是由代码和模板组成。当服务器收到来自之前示例的,它会产生一个响应包含的文件内容。一个优雅的解决方案是允许服务器只发送时间给浏览器,由浏览器转为当地时间并渲染。 4、链接 任何应用程序都有多个路由,必然需要包含链接来连接不同的页面,例如导航栏。 在模板中,对于简单的路由直接写URLs做链接是非常琐碎麻烦的,而给带...
摘要:函数携带目的地址主题邮件体模板和一组关键字参数。许多扩展操作是在假设有活动的应用程序和请求上下文的情况下进行的。但是当函数在一个不同的线程上执行,应用程序上下文需要人为地创建使用。例如,执行函数可以将邮件发送到的任务队列中。 许多类型的应用程序都会在某些事件发生的时候通知用户,常用的沟通方法就是电子邮件。尽管在Flask应用程序中,可以使用Python标准库中的smtplib包来发送电...
摘要:有两类应用级和请求级。一个响应中非常重要的部分是状态码,默认设置来指示请求已经成功处理。重定向通常由响应状态码注明并且重定向的由头部的给出。因为这些变化,应用程序获得一组基本的命令行选项。运行显示可用信息在应用程序上下文的内部运行一个。 5、请求-响应循环 现在你已经玩过一个基本的Flask应用程序,你也许想要知道更多关于Flask如何施展魔力。下面章节描述了一些框架设计方面的特点。...
阅读 1421·2021-09-02 13:57
阅读 1821·2019-08-30 15:55
阅读 2368·2019-08-30 15:54
阅读 2184·2019-08-30 15:44
阅读 2698·2019-08-30 13:18
阅读 435·2019-08-30 13:02
阅读 540·2019-08-29 18:46
阅读 1633·2019-08-29 11:25