Day 18 实作表单 (1)

前言

今天我们要开始使用 Flask-WTF 来做表单,我们要做的表单还不少,但我们每个都会实作。他的概念是用 class 的方式把表单写起来,然後建立一个表单实体并传入 render_template 让 jinja 处理。

我们会加入一个新档案 forms.py,他会放在 app/ 里面。

引入

我们先来引入一些跟 Flask-WTF 有关的东西。

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, PasswordField
from wtforms.fields.html5 import EmailField
from wtforms.validators import DataRequired, Length, EqualTo, Regexp

一开始我们先引入 FlaskForm,他会是我们之後所有表单继承的对象。接下来我们引入了好几个 field,他们基本上就是对应到 HTML 的那些 input type。比较麻烦的是 EmailField 要从 wtforms.fields.html5 引入,之後也会用到一些其他的 field 要从这里引入,最後我们引入了一些 validator,他们是用来验证使用者输入是否正确的,等等我们会一个一个看到。

LoginForm

首先来看看最简单的登入表单,在这里面我们只需要叫使用者输入帐号、密码,然後按下送出即可。在 Flask-WTF 里面,这样就是三个栏位。

class LoginForm(FlaskForm):
    username = StringField(
        "Username", validators=[DataRequired()], render_kw={"placeholder": "Username"}
    )
    password = PasswordField(
        "Password", validators=[DataRequired()], render_kw={"placeholder": "Password"}
    )
    submit = SubmitField("Login")

我们定义了一个 LoginForm,用来处理使用者的登入,接着如刚刚所说,他继承了 FLaskForm。

他有三个栏位,分别是 usernamepasswordsubmit,这些名字并不会显示在网页上,但是我们在处理模板及抓表单资料的时候会用到。接下来我们会分开解释他们及其参数。

  • 第一个是 username,很明显就是用来填使用者名称的。他是一个 StringField,就是放文字的栏位。而他的第一个参数是这个栏位的名字,後面在 jinja 那边会用到,他在 HTML 是 label 的角色。validators 是规定这个栏位要遵守的规则,他是一个 list,Flask-WTF 会一一检查,没过就会视为无效,到时候在写蓝图的时候会看到怎麽判断。这边使用的是 DataRequired,对应到 HTML 就是 input 里面的 required。而他的确会在 HTML 的部份加上 required,但就算手动把它移掉,到後端他还是会检查一次。最後是 render_kw,基本上它就是一些额外的参数,像此处就是指定他的 placeholder,这样在 HTML 那边就会显示出 placeholder="Username",同理,如果想加入 id,就可以在 render_kw 里面加上 "id": "cat" 之类的东西。
  • 第二个是密码的栏位,基本上他跟前面的使用者名称是一样的,他们的差别就只有他是一个 PasswordField,也就是密码栏位,所以它会自动在 HTML 变成 type="password"
  • 第三个不是一个使用者看起来像栏位的东西,他是提交出去的按钮,也就是说 type="submit",而他会用 SubmitField 这个东西。他的第一个参数跟前两个差不多,就是他的名字,但这个名字就会直接变成这个 submit 按钮的文字,在 HTML 就是他的 value

RegisterForm

刚刚第一个表单蛮简单的,就少少三个栏位,但接下来要写的注册帐号表单就没这麽轻松了,先来看看程序码吧。

class RegisterForm(FlaskForm):
    username = StringField(
        "Username",
        validators=[
            DataRequired(),
            Length(min=4, max=30, message="The name should be 4 to 30 letters long."),
            Regexp(
                "[a-zA-Z0-9_]+",
                message="Only letters, numbers and underscore are allowed in username.",
            ),
        ],
        render_kw={"placeholder": "Username"},
    )
    password = PasswordField(
        "Password",
        validators=[
            DataRequired(),
            Length(min=6, message="The password must contain at least 6 characters."),
        ],
        render_kw={"placeholder": "Password"},
    )
    repeat_password = PasswordField(
        "Repeat Password",
        validators=[
            DataRequired(),
            EqualTo("password", message="Passwords not match."),
        ],
        render_kw={"placeholder": "Repeat Password"},
    )
    email = EmailField(
        "Email", validators=[DataRequired()], render_kw={"placeholder": "Email"}
    )
    submit = SubmitField("Register")

其实这次也就只有五个栏位,但是每一个栏位都有一堆麻烦的设定,我们一个一个来看。

  • 第一个栏位是使用者名称,我们在 validators 加了不少东西。首先是刚刚就有的 DataRequired,在此不再多说了。接下来是 Length,它是用来限制长度的,maxmin 分别代表上下限,後面的 message 是当这个条件不被满足时所要跳出的讯息 (在 DataRequired 也可以指定 message,在写蓝图的时候我们会处理这个讯息并 flash 到前端。最後一个是 Regexp,就是正规表示式 (regular expression) 的意思,在这边我们限制这个使用者名称只能由英文字母、数字、下底线组成,如同下面的 message 所写。
  • 第二个是密码,一样要有 DataRequired,同时也限制最短密码要有六个字元,没有上限。
    第三个是确认密码的栏位,所以在他的 validators 我们加入了 EqualTo,他的第一个参数是要跟哪一个 field 有相同的值,要放的是变数名称,但用的是字串 ("password"),而不是变数本身 (password)。
  • 第四个是填写电子邮件的栏位,刚刚没有出现过,要使用 EmailField
  • 最後一个栏位跟刚刚接近,就是提交的按钮,但在此处我们 value 设成 Register

References

Automatically setting the id HTML attribute of a form element in flask-wtforms
HTML input Tag


<<:  Day 18 Chatbot integration- Face Login- 人脸登入

>>:  [Day18] NLP会用到的模型(二)-GRU

DAY 5:Thread-Per-Message Pattern,预备...发射!

在 DAY 2~DAY 4 我们使用到了 goroutine、lock、channel,主要目标在保...

day9 稽核 (雷)除了技术,也要学管理

来部落格看图文并茂文章 补觉鸣诗 所谓的稽核 很多人都会担心做不好就惩处 导致稽核前大家人仰马翻 其...

【Day 29】实作 - 如何设定 AWS CloudWatch Alarms

昨天我们讨论到我们可以从 AWS console 的 EC2 服务查看 Instance statu...

D-30-安装 vscode ? dotnet sdk

离实习结束还有30天 实习生小光第一天到新公司实习,什麽都不懂的他到底会遇到什麽事情呢,让大家想想第...

Gulp 合并来自 npm 的 Javascript的资源 DAY96

在载入 bootstrap 的 js之前 我们可以看到 https://getbootstrap.c...