pip
安装。 那就继续在你的虚拟环境中安装Flask-WTF吧:app.config
对象,它是一个类似字典的对象,可以将配置以键值的方式存储其中。例如,你可以这样做:Config
类中的属性。 一旦应用程序需要更多配置选项,直接依样画葫芦,附加到这个类上即可,稍后如果我发现需要多个配置集,则可以创建它的子类。现在则不用操心。SECRET_KEY
是我添加的唯一配置选项,对大多数Flask应用来说,它都是极其重要的。Flask及其一些扩展使用密钥的值作为加密密钥,用于生成签名或令牌。Flask-WTF插件使用它来保护网页表单免受名为Cross-Site Request Forgery或CSRF(发音为“seasurf”)的恶意攻击。顾名思义,密钥应该是隐密的,因为由它产生的令牌和签名的加密强度保证,取决于除了可信维护者之外,没有任何人能够获得它。or
运算符连接两个项的表达式。第一个项查找环境变量SECRET_KEY
的值,第二个项是一个硬编码的字符串。这种首先检查环境变量中是否存在这个配置,找不到的情况下就使用硬编码字符串的配置变量的模式你将会反复看到。在开发阶段,安全性要求较低,因此可以直接使用硬编码字符串。但是,当应用部署到生产服务器上的时候,我将设置一个独一无二且难以揣摩的环境变量,这样,服务器就拥有了一个别人未知的安全密钥了。app.config.from_object()
方法来完成这个操作:Config
类的方式,乍一看可能会让人感到困惑,不过如果你注意到从flask
包导入Flask
类的过程,就会发现这其实是类似的操作。 显而易见,小写的“config”是Python模块config.py的名字,另一个含有大写“C”的是类。app.config
中的字典语法来访问配置项。 在下面的Python交互式会话中,你可以看到密钥的值:flask_ <name>
命名约定来导入,Flask-WTF的所有内容都在flask_wtf
包中。在本例中,app/forms.py模块的顶部从flask_wtf
导入了名为FlaskForm
的基类。LoginForm
的类属性。validators
用于验证输入字段是否符合预期。DataRequired
验证器仅验证字段输入是否为空。更多的验证器将会在未来的表单中接触到。LoginForm
类的实例化,不过我现在还没有编写它。<form>
元素被用作Web表单的容器。 表单的action
属性告诉浏览器在提交用户在表单中输入的信息时应该请求的URL。 当action
设置为空字符串时,表单将被提交给当前地址栏中的URL,即当前页面。 method
属性指定了将表单提交给服务器时应该使用的HTTP请求方法。 默认情况下是用GET
请求发送,但几乎在所有情况下,使用POST
请求会提供更好的用户体验,因为这种类型的请求可以在请求的主体中提交表单数据, GET
请求将表单字段添加到URL,会使浏览器地址栏变得混乱。form.hidden_tag()
模板参数生成了一个隐藏字段,其中包含一个用于保护表单免受CSRF攻击的token
。 对于保护表单,你需要做的所有事情就是在模板中包括这个隐藏的字段,并在Flask配置中定义SECRET_KEY
变量,Flask-WTF会完成剩下的工作。{{ form.<field_name>.label }}
,需要这个字段的地方加上{{ form.<field_name>() }}
。 对于需要附加HTML属性的字段,可以作为关键字参数传递到函数中。 此模板中的username和password字段将size
作为参数,将其作为属性添加到<input>
HTML元素中。 你也可以通过这种手段为表单字段设置class和id属性。LoginForm
类,并生成了一个实例传入模板。form=form
的语法看起来奇怪,这是Python函数或方法传入关键字参数的方式,左边的form
代表在模板中引用的变量名称,右边则是传入的form实例。这就是获取表单字段渲染结果的所有代码了。http://localhost:5000/
,然后点击顶部导航栏中的“Login”链接来查看新的登录表单。 是不是非常炫酷?methods
参数。 它告诉Flask这个视图函数接受GET
和POST
请求,并覆盖了默认的GET
。 HTTP协议规定对GET
请求需要返回信息给客户端(本例中是浏览器)。 本应用的所有GET
请求都是如此。 当浏览器向服务器提交表单数据时,通常会使用POST
请求(实际上用GET
请求也可以,但这不是推荐的做法)。之前的“Method Not Allowed”错误正是由于视图函数还未配置允许POST
请求。 通过传入methods
参数,你就能告诉Flask哪些请求方法可以被接受。form.validate_on_submit()
实例方法会执行form校验的工作。当浏览器发起GET
请求的时候,它返回False
,这样视图函数就会跳过if
块中的代码,直接转到视图函数的最后一句来渲染模板。POST
请求。form.validate_on_submit()
就会获取到所有的数据,运行字段各自的验证器,全部通过之后就会返回True
,这表示数据有效。不过,一旦有任意一个字段未通过验证,这个实例方法就会返回False
,引发类似GET
请求那样的表单的渲染并返回给用户。稍后我会在添加代码以实现在验证失败的时候显示一条错误消息。form.validate_on_submit()
返回True
时,登录视图函数调用从Flask导入的两个新函数。 flash()
函数是向用户显示消息的有效途径。 许多应用使用这个技术来让用户知道某个动作是否成功。我将使用这种机制作为临时解决方案,因为我没有基础架构来真正地登录用户。 显示一条消息来确认应用已经收到登录认证凭据,我认为对当前来说已经足够了。redirect()
。这个函数指引浏览器自动重定向到它的参数所关联的URL。当前视图函数使用它将用户重定向到应用的主页。flash()
函数后,Flask会存储这个消息,但是却不会奇迹般地直接出现在页面上。模板需要将消息渲染到基础模板中,才能让所有派生出来的模板都能显示出来。更新后的基础模板代码如下:with
结构在当前模板的上下文中来将get_flashed_messages()
的结果赋值给变量messages
。get_flashed_messages()
是Flask中的一个函数,它返回用flash()
注册过的消息列表。接下来的条件结构用来检查变量messages
是否包含元素,如果有,则在<ul>
元素中,为每条消息用<li>
元素来包裹渲染。这种渲染的样式结果看起来不会美观,之后会有主题讲到Web应用的样式。get_flashed_messages
函数请求了一次,它们就会从消息列表中移除,所以在调用flash()
函数后它们只会出现一次。DataRequired
验证器是如何中断提交处理流程的。form.<field_name>.errors
来渲染错误信息。 一个字段的验证错误信息结果是一个列表,因为字段可以附加多个验证器,并且多个验证器都可能会提供错误消息以显示给用户。redirect()
函数作为参数的链接:url_for()
的函数,它使用URL到视图函数的内部映射关系来生成URL。 例如,url_for('login')
返回/login
,url_for('index')
返回/index
。 url_for()
的参数是endpoint名称,也就是视图函数的名字。url_for()
生成这种复杂的URL就方便许多。url_for()
。基础模板中的导航栏部分代码变更如下:login()
视图函数也做了相应变更: