Flask 教程,第三部分:Web 表单 已翻译 100%

oschina 投递于 2012/12/28 09:03 (共 22 段, 翻译完成于 01-08)
阅读 67876
收藏 13
4
加载中

This is the third article in the series in which I document my experience writing web applications in Python using the Flask microframework.

The goal of the tutorial series is to develop a decently featured microblogging application that demonstrating total lack of originality I have decided to callmicroblog.

Here is an index of all the articles in the series that have been published to date:

已有 1 人翻译此段
我来翻译
Recap

In the previous chapter of the series we defined a simple template for the home page and used fake objects as placeholders for things we don't have yet, like users or blog posts.

In this article we are going to fill one of those many holes we still have in our app, we will be looking at how to work with web forms.

Web forms are one of the most basic building blocks in any web application. We will be using forms to allow users to write blog posts, and also for logging in to the application.

To follow this chapter along you need to have themicroblogapp as we left it at the end of the previous chapter. Please make sure the app is installed and running.

已有 1 人翻译此段
我来翻译

Configuration

To handle our web forms we are going to use the Flask-WTF extension, which in turn wraps the WTForms project in a way that integrates nicely with Flask apps.

Many Flask extensions require some amount configuration, so we are going to setup a configuration file inside our rootmicroblogfolder so that it is easily accessible if it needs to be edited. Here is what we will start with (fileconfig.py):

CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'

Pretty simple, it's just two settings that our Flask-WTF extension needs. TheCSRF_ENABLEDsetting activates the cross-site request forgery prevention. In most cases you want to have this option enabled as it makes your app more secure.

已有 1 人翻译此段
我来翻译

TheSECRET_KEYsetting is only needed with CSRF is enabled, and is used to create a cryptographic token that is used to validate a form. When you write your own apps make sure to set the secrete key to something that is difficult to guess.

Now that we have our config file we need to tell Flask to read it and use it. We can do this right after the Flask app object is created, as follows (fileapp/__init__.py):

from flask import Flask

app = Flask(__name__)
app.config.from_object('config')

from app import views
已有 1 人翻译此段
我来翻译

The user login form

Web forms are represented in Flask-WTF as objects, subclassed from classForm. A form subclass simply defines the fields of the form as class variables.

We will create a login form that users will use to identify with the system. The login mechanism that we will support in our app is not the standard username/password type, we will have our users login using their OpenID. OpenIDs have the benefit that the authentication is done by the provider of the OpenID, so we don't have to validate passwords, which makes our site more secure to our users.

已有 1 人翻译此段
我来翻译

The OpenID login only requires one string, the so called OpenID. We will also throw a 'remember me' checkbox in the form, so that users can choose to have a cookie installed in their browsers that remembers their login when they come back.

So let's write our first form (fileapp/forms.py):

from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required

class LoginForm(Form):
    openid = TextField('openid', validators = [Required()])
    remember_me = BooleanField('remember_me', default = False)

I believe the class is pretty much self-explanatory. We imported theFormclass, and the two field classes that we need,TextFieldandBooleanField.

TheRequiredimport is a validator, a function that can be attached to a field to perform validation on the data submitted by the user. TheRequiredvalidator simply checks that the field is not submitted empty. There are many more validators included with Flask-WTF, we will use some more in the future.

已有 1 人翻译此段
我来翻译

Form templates

We will also need a template that contains the HTML that produces the form. The good news is that theLoginFormclass that we just created knows how to render form fields as HTML, so we just need to concentrate on the layout. Here is our login template (fileapp/templates/login.html):

<!-- extend from base layout -->
{% extends "base.html" %}

{% block content %}
<h1>Sign In</h1>
<form action="" method="post" name="login">
    {{form.hidden_tag()}}
    <p>
        Please enter your OpenID:<br>
        {{form.openid(size=80)}}<br>
    </p>
    <p>{{form.remember_me}} Remember Me</p>
    <p><input type="submit" value="Sign In"></p>
</form>
{% endblock %}

Note that in this template we are reusing thebase.htmltemplate through theextendstemplate inheritance statement. We will actually do this with all our templates, to ensure a consistent layout across all pages.

已有 1 人翻译此段
我来翻译

There are a few interesting differences between a regular HTML form and our template. The template expects a form object instantiated from the form class we just defined stored in a template argument namedform. We will take care of sending this template argument to the template next, when we write the view function that renders this template.

Theform.hidden_tag()template argument will get replaced with a hidden field that implements the CSRF prevention that we enabled in the configuration. This field needs to be in all your forms if you have CSRF enabled.

已有 1 人翻译此段
我来翻译

The actual fields of our form are also rendered by the form object, you just have to refer to a{{form.field_name}}template argument in the place where the field should be inserted. Some fields can take arguments. In our case, we are asking the form to generate ouropenidfield with a width of 80 characters.

Since we have not defined the submit button in the form class we have to define it as a regular field. The submit field does not carry any data so it doesn't need to be defined in the form class.

已有 1 人翻译此段
我来翻译

Form views

The final step before we can see our form is to code a view function that renders the template.

This is actually quite simple since we just need to pass a form object to the template. Here is our new view function (fileapp/views.py):

from flask import render_template, flash, redirect
from app import app
from forms import LoginForm

# index view function suppressed for brevity

@app.route('/login', methods = ['GET', 'POST'])
def login():
    form = LoginForm()
    return render_template('login.html', 
        title = 'Sign In',
        form = form)

So basically, we have imported ourLoginFormclass, instantiated an object from it, and sent it down to the template. This is all that is required to get form fields rendered.

Let's ignore for now theflashandredirectimports. We'll use them a bit later.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(25)

helloHeng
helloHeng

引用来自“不必在乎朕是谁”的评论

引用来自“zhangdedezhu”的评论

No module named flask.ext.wtf 一直提示这个错误,但是明明在第一步的时候装过了,这是为什么

http://docs.torriacg.org/docs/flask/patterns/wtforms.html
貌似这个包变成了 WTForms
尝试这样或许可行
from flask_wtf import FlaskForm
风过暖城
风过暖城

引用来自“jeffsui”的评论

问题解决了,flask0.9版本之后,需要安装flask-wtf和WTForms,然后修改导入的包:
from flask.ext.wtf import Form
from wtforms.fields import TextField,StringField,BooleanField
from wtforms.validators import DataRequired
就可以了

引用来自“夜不成寐”的评论

运行以后报错views.py,No module named 'forms',明明forms.py 和views.py是放在同一目录下的,求解
在view.py中应该是from .forms import LoginForm
夜不成寐
夜不成寐

引用来自“jeffsui”的评论

问题解决了,flask0.9版本之后,需要安装flask-wtf和WTForms,然后修改导入的包:
from flask.ext.wtf import Form
from wtforms.fields import TextField,StringField,BooleanField
from wtforms.validators import DataRequired
就可以了
运行以后报错views.py,No module named 'forms',明明forms.py 和views.py是放在同一目录下的,求解
jeffsui
jeffsui
问题解决了,flask0.9版本之后,需要安装flask-wtf和WTForms,然后修改导入的包:
from flask.ext.wtf import Form
from wtforms.fields import TextField,StringField,BooleanField
from wtforms.validators import DataRequired
就可以了
c
code_cheers

引用来自“罗泽轩”的评论

原文中的:
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
在flask-wtf的0.9版之后已经不可用。
见 https://flask-wtf.readthedocs.org/en/latest/upgrade.html#version-0-9-0
0.9版之后的flask-wtf的结构有了不小的改动,如果遇到问题,可以先去看看官方文档。
新版本用这种方式引用: from flask.ext.wtf import Form from wtforms.fields import TextField,BooleanField from wtforms.validators import Required
litao6015
litao6015

引用来自“zhangdedezhu”的评论

引用来自“不必在乎我是谁”的评论

引用来自“zhangdedezhu”的评论

No module named flask.ext.wtf 一直提示这个错误,但是明明在第一步的时候装过了,这是为什么

http://docs.torriacg.org/docs/flask/patterns/wtforms.html
貌似这个包变成了 WTForms

我建议你还是看原版英文文档,好多问题都可以避免的
这个的英文原版在哪儿呢,能发个链接吗?
X-Alvin
X-Alvin

引用来自“X-Alvin”的评论

登入login显示:unbound method hidden_tag() must be called with LoginForm instance as first argument (got nothing instead)怎么解决啊,我知道是实例化的问题,不过form不是已经是实例化的了么
已解决,代码有误,sorry
X-Alvin
X-Alvin
登入login显示:unbound method hidden_tag() must be called with LoginForm instance as first argument (got nothing instead)怎么解决啊,我知道是实例化的问题,不过form不是已经是实例化的了么
爱已欠费停机

引用来自“罗泽轩”的评论

原文中的:
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
在flask-wtf的0.9版之后已经不可用。
见 https://flask-wtf.readthedocs.org/en/latest/upgrade.html#version-0-9-0
0.9版之后的flask-wtf的结构有了不小的改动,如果遇到问题,可以先去看看官方文档。

引用来自“爱已欠费停机”的评论

ImportError: No module named flask.ext.wtf 报这错的时候得装这个 pip install -U Flask-WTF 接着把forms.py这里改为 from flask.ext.wtf import Form from wtforms import TextField, BooleanField from wtforms.validators import Required 及可运行
看我的回复可以解决
爱已欠费停机

引用来自“罗泽轩”的评论

原文中的:
from flask.ext.wtf import Form, TextField, BooleanField
from flask.ext.wtf import Required
在flask-wtf的0.9版之后已经不可用。
见 https://flask-wtf.readthedocs.org/en/latest/upgrade.html#version-0-9-0
0.9版之后的flask-wtf的结构有了不小的改动,如果遇到问题,可以先去看看官方文档。
ImportError: No module named flask.ext.wtf 报这错的时候得装这个 pip install -U Flask-WTF 接着把forms.py这里改为 from flask.ext.wtf import Form from wtforms import TextField, BooleanField from wtforms.validators import Required 及可运行
返回顶部
顶部
返回顶部
顶部