首頁 > 軟體

Flask中的表單實現頁面註冊

2020-06-16 16:47:48

使用flask-migrate

almebic是一個資料庫版本管理的工具,在對一個資料表進行新增列,刪除列的時候相當於進行了資料庫版本的改變。flask-migrate是對almbic進行的封裝,方便在flask中使用alembic管理資料庫。

使用flask-migrate首先要在create_app的時候將它註冊到app上。

from flask_migrate import Migrate

def create_app(config):
    app = Flask(__name__)
    app.config.from_object(configs.get(config))
    db.init_app(app)
    Migrate(app, db)
    register_blueprints(app)
    return app

設定後完成執行

flask db

第一次使用需要進行初始化

flask db init

執行:

flask db migrate -m 'init database'

這個命令會在version目錄下生成一個資料庫升級指令碼,-m後是本次提交的相關資訊,檢查無誤後可以執行

flask db upgrade

將升級寫入資料庫

使用flask-wtf

wtforms是Python實現的一個庫,它能在python和HTML form之間建立一種對映關係,類似ORM,方便建立表單和在模板中渲染表單。flask-wtf則是對wtforms的封裝,方便在flask中使用wtforms,並在wtforms的基礎上新增了crsf token的生成和驗證機制。使用flask-wtf,需要定義的表單中繼承flask-wtf提供的FlaskForm基礎類別,並為每一個表單輸入一個宣告欄位。

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import Length, Email, EqualTo, Required

class RegisterForm(FlaskForm):
    username = StringField('使用者名稱', validators=[Required(), Length(3, 24)])
    email = StringField('郵箱', validators=[Required(), Email()])
    password = PasswordField('密碼', validators=[Required(), Length(6, 24)])
    repeat_password = PasswordField('重複密碼', validators=[Required(), EqualTo('password')])
    submit = SubmitField('提交')

class LoginForm(FlaskForm):
    email = StringField('郵箱', validators=[Required(), Email()])
    password = PasswordField('密碼', validators=[Required(), Length(6, 24)])
    remember_me = BooleanField('記住我')
    submit = SubmitField('提交')

要在Form類為每個輸入框宣告一個對應的Field,Field一般提供兩個引數,第一個是輸入框html中的label,第二個一般是validators(驗證器)。validators是一個列表,可以放入多個驗證器,表單提交時,wtforms會使用列表裡的驗證器對提交的資料進行驗證,驗證失敗的資料,wtforms會將失敗資訊寫入Field下的errors列表下。

在註冊路由的python檔案中將相應的form傳遞到模板中

from **.forms import LoginForm, RegisterForm

@front.route('/login')
def login():
    form = LoginForm()
    return render_template('login.html', form=form)

然後在login.html中進行表單的渲染。

{% extends "base.html" %}

{% block title %}
Login
{% endblock %}

{% block body %}
  <h2>登入</h2>
  <!-- 要在 form 裡指定 POST 方法和點選提交後需要請求的 url -->
  <form method="POST" action="{{ url_for('front.login') }}">
    <!-- flask-wtf 幫我們在表單類中新增了 csrf_token,我們只要簡單的渲染就可以了, 渲染後會在 hmtl 頁面生成一個隱藏域,裡面是 csrf_token 值 -->
    {{ form.csrf_token }}

    <!-- 使用 Bootstrap 的表單樣式渲染每個表單項 -->
    <div class="form-group">
      <!-- 首先渲染 field label -->
      <!-- 接著渲染 field,StringField 渲染後會生成一個 <input> 標籤,field 裡面可以傳入 html 的標籤屬性,這些屬性會渲染到生成的 html 標籤中 -->
      {{ form.email.label }} {{ form.email(class='form-control') }}
    </div>

    <div class="form-group">
      {{ form.password.label }} {{ form.password(class='form-control') }}
    </div>

    <!-- BooleanField 的渲染有些特殊,使用了 Bootstrap 的 checkbox 類-->
    <div class="checkbox">
      <label>
        {{ form.remember_me() }}
<!-- 注意這裡獲取的是 label 的 text 屬性,也就是我們在表單中定義的"記住我"這個字串-->
{{ form.remember_me.label.text }}
      </label>
    </div>
    <!-- 渲染提交按鈕,傳入 Bootstrap 的按鈕類-->
    {{ form.submit(class="btn btn-primary") }}
  </form>
{% endblock %}

由於在同一個網站中的表單結構和內容是相似的,因此可以使用macro對重複的動作進行封裝,使用的是jinjia2的語法。

{% macro macro_name(arg1, arg2, ...)%}
....
{% endmacro %}

macro通常存放在macro.html中,使用該檔案的某個macro時,使用Import匯入即可

{% from "macro.html" import macro_name %}

使用{{}}格式語法進行呼叫

{{ macro_name(arg1, arg2 )}}

下面是一個render_form的宏用於渲染表單

<!-- 需要傳入2個引數:要渲染的 form 和點選提交請求的 url -->
{% macro render_form(form, url) %}
<form method="POST" action="{{ url }}">
  <!-- 將 csrf_token 渲染在表單開始的位置 -->
  {{ form.csrf_token }}
  <!-- 疊代每個表單 field -->
  {% for field in form %}
    <!-- 如果是 csrf_token 就不再渲染了 -->
    {% if field.type == 'CSRFTokenField' %}
    {{ '' }}
    <!-- SubmitField 單獨特殊處理 -->
    {% elif field.type == 'SubmitField' %}
    {{ form.submit(class='btn btn-primary', type='submit') }}
    <!-- BooleanField 單獨特殊處理 -->
    {% elif field.type == 'BooleanField' %}
    <div class="checkbox">
      <label>{{ field() }} {{ field.label.text }}</label>
    </div>
    {% else %}
    <div class="form-group">
      {{ field.label }} {{ field(class='form-control') }}
    </div>
    {% endif %}
  {% endfor %}
</form>
{% endmacro %}

將login.html使用render_form渲染:

{% extends "base.html" %}
{% from "macros.html" import render_form %}

{% block title %}Login{% endblock %}

{% block body %}
<div class="form">
  <h2>登入</h2>
  {{ render_form(form, url_for('front.login')) }}
</div>
{% endblock %}

然後在RegisterForm下實現根據表單提交的資料建立使用者

from simpledu.models import db, User

class RegisterForm(FlaskForm):
    ...

    def create_user(self):
        user = User()
        user.username = self.username.data
        user.email = self.email.data
        user.password=self.password.data
        db.session.add(user)
        db.session.commit()
        return user

在front.py中實現註冊功能的路由處理常式:

from flask import flash
from flask import redirect,url_for

@front.route('/register', methods=['GET', 'POST'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        form.create_user()
        flash('註冊成功,請登入!', 'success')
        return redirect(url_for('.login'))
    return render_template('register.html', form=form)

validate_on_submit是flask-wtf提供的FlaskForm中封裝的一個方法,返回值是一個布林值。如果表單提交了並且我們在對應的form中宣告的表單資料驗證器對使用者提交的表單資料驗證通過,那麼該方法返回True,否則返回False。

上面的程式碼中,表單提交並且資料驗證成功後,條用我們之前實現的方法建立使用者。有時候,網站需要對使用者的一些操作給出成功、失敗、警告等一系列反饋,我們呼叫了flash函數,該函數的功能是向模板頁面傳送一訊息,它接受兩個引數,訊息的內容和分類,最後重定向到登陸頁面。

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

本文永久更新連結地址https://www.linuxidc.com/Linux/2018-08/153710.htm


IT145.com E-mail:sddin#qq.com