Flask實踐Step by Step -- Web表單

Flask開發(fā)環(huán)境配置
Flask快速入門
Flask實踐Step by Step -- 'Hello World'
Flask實踐Step by Step -- 模板
Flask實踐Step by Step -- Web表單

Flask Web Forms

上一節(jié)我們定義了一個簡單的模板,并看到了實際運行的效果,接下來我們來看一下Web表單是如何
工作的,Web表單是Web應用程序的基礎控件,使用表單可以使用用戶寫博客,進行登錄等

配置

為了使用表單,我們需要使用Flask的一個擴展插件 Flask-WTF 需要先安裝 pip install flask-wtf ,
許多Flask擴展需要很多的配置,我需要一個配置文件來進行管理 config.py

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

配置文件中的內容非常簡單,需要兩項設置即可,WTF_CSRF_ENABLED設置會激活跨站訪問保護
這個設置在這個版本中Flask-WTF是默認打開的,為了更安全我們這里還是顯示的設置為 True
SECRECT_KEY的設置只有當WTF_CSRF_ENABLED為true時才會需要,為表單驗證創(chuàng)建一個密碼
token,這個key值盡量設置的復雜一些
接下來就需要Flask讀取相關的配置,并且使用這些配置,在Flask的應用程序創(chuàng)建之后(file app/__init__.py)

from flask import Flask

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

from app import views

用戶登錄表單

Flask-WTF的表單是一個集成基類Form的一個類,現(xiàn)在我們需要創(chuàng)建一個登錄的表單,需要用到身份認證系統(tǒng)
登錄機制不是標準的 用戶名/密碼 模式,我們在這里引入了 OpendID,OpenID本身已經提供了
很好的驗證,我們就不在需要驗證密碼了,這樣可以使網站更安全,需要安裝OpenID pip install flask-openid
使用OpenID登錄只需要一個字符串,我們還提供了一個 'remember me' 選擇框,用戶可以選擇是否需要瀏覽器在cookie中記住
用戶的選擇
寫第一個表單 (file app/forms.py)

from flask.ext.wtf import Form
from wtforms import StringField,BooleanField
from wtforms.validators import DataRequired

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

很簡單的一個類,繼承Form兩個字段,StringFieldBooleanField,DataRequired是一個驗證器
一個方法和一個字段綁定,這個DataRequired驗證器只是簡單的驗證提交的輸入內容,這Flask-WTF中還有很多
驗證器,后續(xù)會繼續(xù)介紹

表單模板

我們需要一個模板來生成HTML的表單,我們需要創(chuàng)建一個新的模板 (file app/templates/login.html)

{% extends "base.html" %}

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

這個模板中同樣是繼承base.html,這個模板和普通的HTML頁面的表單還是有一些區(qū)別的,需要
視圖中對應的方法來血染這個模板,form.hidden_tag()會被HTML中的隱藏的域來取代,這個參數(shù)
需要把CSRF設置為Enabled狀態(tài)

表單視圖

我們需要一個視圖方法來渲染這個模板(file app/views.py)

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

#index view function...

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

需要引入 LoginForm這類,然后實例化,將這個實例化對象作為參數(shù)傳入到模板中,我們還引入了
flashredirect,可以暫時忽略這兩個引用,以后我們會用到,在裝飾器中我們加入了 methods
作為參數(shù),告訴Flask我們的這個方法接收 GET和POST請求,保存運行,打開瀏覽器 訪問 http://127.0.0.1:5000/login
看一下實際的效果,暫時我們還沒有處理接收數(shù)據(jù)的處理,所以現(xiàn)在點擊提交按鈕會沒有任何反饋

接收數(shù)據(jù)

Flask-WTF能夠很容易處理從客戶端發(fā)來的數(shù)據(jù),我們需要修改一下 login的方法(file app/views.py)

@app.route('/login',methods=['GET','POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        flash('Login requested for OpenID=""%s",remember_me=%s'%
                (form.openid.data,str(form.remember_me.data)))
        return redirect('/index')
    return render_template('login.html',
                            title="Sign in",
                            form=form)

方法 validate_on_submit會處理所有的表單的處理工作,表單展示給用戶時會調用這個方法此時會返回 False
當提交請求時,這個方法會接收所有的數(shù)據(jù),驗證數(shù)據(jù)的合法性,如果驗證全部正確,這個方法會返回True,只要有一個
參數(shù)驗證不通過,這個方法就會返回 False,稍后我們會展示如何給用戶展示錯誤信息,當 validate_on_submit返回True
時,方法 flash會展示一個快速的信息,在調到下一個頁面之前,這個flash的信息不回顯示在頁面中,我們需要修改模板信息
來顯示這個信息(file app/templates/base.html)

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    {% if title %}
    <title>{{ title }} - microblog</title>
    {% else %}
    <title>Welcome to microblog</title>
    {% endif %}
  </head>
  <body>
    <div>
      Microblog : <a href="/index">Home</a>
    </div>
    <hr>
    {% with messages = get_flashed_messages()%}
      {% if messages %}
        <ul>
          {% for msg in messages %}
            <li>{{ msg }}</li>
          {% endfor %}
        </ul>
      {% endif %}
    {% endwith %}
    {% block content %}{% endblock %}
  </body>
</html>

方法get_flashed_messages會接收flash方法發(fā)送來的消息,并展示出來,在視圖方法中我們還使用另一個
方法 redirect,這個方法會重定向到另一網頁地址

改進數(shù)據(jù)的驗證

當用戶的輸入的信息有誤時,希望能夠提供給用戶友好的錯誤的信息提示,我們修改一下login的模板(file app/templates/login.html)

{% extends "base.html" %}

{% block content %}
  <h1>Sign in</h1>
  <form class="" action="" name="login" method="post">
    {{form.hidden_tag()}}
    <p>
      Please enter your OpenID:<br>
      {{ form.openid(size=80) }}
      {% for error in form.openid.errors %}
        <span style="color:red;">[{{ error }}]</span>
      {% endfor %}
    </p>
    <p>
      {{ form.remember_me }} Remember Me
    </p>
    <p>
      <input value="Sign in" type="submit">
    </p>
  </form>
{% endblock %}

添加了錯誤的提示信息

處理OpenIDs

為了是用戶更容易的登錄網站,我們添加一些openid的連接,兒不需要用戶手動的輸入OpenID
先定義一些OpenID的提供者,定義在config.py

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

OPENID_PROVIDERS = [
    {'name': 'Google', 'url': 'https://www.google.com/accounts/o8/id'},
    {'name': 'Yahoo', 'url': 'https://me.yahoo.com'},
    {'name': 'AOL', 'url': 'http://openid.aol.com/<username>'},
    {'name': 'Flickr', 'url': 'http://www.flickr.com/<username>'},
    {'name': 'MyOpenID', 'url': 'https://www.myopenid.com'}]

然后在視圖方法中使用

@app.route('/login',methods=['GET','POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        flash('Login requested for OpenID=""%s",remember_me=%s'%
                (form.openid.data,str(form.remember_me.data)))
        return redirect('/index')
    return render_template('login.html',
                            title="Sign in",
                            form=form,
                            providers=app.config['OPENID_PROVIDERS'])

還需要修改對應的模板視圖(file app/templates/login.html)

{% extends "base.html" %}

{% block content %}

<script type="text/javascript">
  function set_openid(openid,pr){
    u = openid.search('<username>')
    if(u != -1){
      user = prompt('Enter your '+ pr + 'username')
      openid = openid.substr(0,u)+user
    }
    form = document.forms['login']
    form.elements['openid'].value = openid
  }
</script>

  <h1>Sign in</h1>
  <form class="" action="" name="login" method="post">
    {{form.hidden_tag()}}
    <p>
      Please enter your OpenID:<br>
      {{ form.openid(size=80) }}
      {% for error in form.openid.errors %}
        <span style="color:red;">[{{ error }}]</span>
      {% endfor %}<br>
      | {% for pr in providers %}
          <a href="javascript:set_openid('{{ pr.url }}','{{pr.name}}')">{{ pr.name }}</a> |
      {% endfor %}
    </p>
    <p>
      {{ form.remember_me }} Remember Me
    </p>
    <p>
      <input value="Sign in" type="submit">
    </p>
  </form>
{% endblock %}

運行截圖

寫在最后

我們隊登錄的表單做了很多的改進,但是我們還沒有真正的登錄到系統(tǒng)中,真正的登錄我們需要后臺的數(shù)據(jù)庫的支持

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容