flask實戰-我的博客-表單

表單

下面咱們來編寫全部表單類,personalBlog中主要包含下面這些表單:數據庫

登陸表單;flask

文章表單;app

評論表單;函數

博客設置表單;ui

 

這裏僅介紹登陸表單、文章表單、分類表單和評論表單,其餘的表單在實現上基本相同。spa

 

刪除資源也須要使用表單來實現,這裏之因此沒有建立表單類,是由於後面咱們會介紹在實現刪除操做時爲表單實現CSRF保護的更方便的作法。code

 

一、登陸表單

用於登陸的LoginForm表單類的實現以下所示:orm

personalBlog/forms.py: 登陸表單csrf

 

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired

class LoginForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(1, 20)])
    password = PasswordField('Password', validators=[DataRequired(), Length(8, 128)])
    remember = BooleanField('Remember me')
    submit = SubmitField('Log in')

 

登陸表單由用戶名字段(username)、密碼字段(password)、「記住我」複選框(remember)和「提交」按鈕(submit)組成。其中使用了兩個新字段: 一個是表示<input type=」password」>的密碼字段PasswordField,它會使用黑色原點來表示密碼;另外一個是表示<input type=」checkbox」>的複選框字段BooleanField,它會返回布爾值做爲數據。blog

 

二、文章表單

用於建立文章的PostForm表單類的實現以下所示:

personalBlog/forms.py: 文章表單

 

from flask_ckeditor import CKEditorField
from wtforms import SelectField
from wtforms.validators import DataRequired, Length

from personalBlog.models import Category

class PostForm(FlaskForm):
    title = StringField('Title', validators=[DataRequired(), Length(1, 60)])
    category = SelectField('Category', coerce=int, default=1)
    body = CKEditorField('Body', validators=[DataRequired()])
    submit = SubmitField()
    
    def __init__(self, *args, **kwargs):
        super(PostForm, self).__init__(*args, **kwargs)
        self.category.choices = [(category.id, category.name)
            for category in Category.query.order_by(Category.name).all()]

 

文章建立表單由標題字段(title)、分類選擇字段(category)、正文字段(body)和「提交」按鈕組成,其中正文字段使用Flask-CKEditor提供的CKEditorField字段。

 

下拉列表字段使用WTForms提供的SelectField類來表示HTML中的<select>標籤。下拉列表的選項(即<option>標籤)經過參數choices指定。choices必須是一個包含量元素元祖的列表,列表中的元祖分別包含選項值和選項標籤。咱們使用分類的id做爲選項值,分類的名稱做爲選項標籤,這兩個值經過迭代Category.query.order_by(Category.name).all()返回的分類記錄實現。選擇值摩恩爲字符串類型,咱們使用coerce關鍵字指定數據類型爲整形。default用來設置默認的選項值,咱們將其指定爲1,即默認分類的id。

 

由於Flask-SQLAlchemy依賴於程序上下文才能正常工做(內部使用current_app獲取配置信息),因此這個查詢調用要放到構造方法中執行,在構造方法中對self.category.choices賦值的效果和在類中實例化SelectField類並設置choices參數相同。

 

三、分類表單

用於建立分類的CategoryForm表單類的實現以下所示:

personalBlog/forms.py: 分類建立表單

 

from wtforms.validators import DataRequired
from wtforms import ValidationError
from personalBlog.models import Category

class CatetoryForm(FlaskForm):
    name = StringField('Name', validators = [DataRequired(), Length(1, 30)])
    submit = SubmitField()
    
    def validate_name(self, field):
        if Category.query.filter_by(name = field.data).first():
            raise ValidationError('Name already in use.')

 

分類建立字段僅包含分類名稱字段(name)和提交字段。分類的名稱要求不能重複,爲了不寫入重複的分類名稱致使數據庫出錯,咱們在CategoryForm類中添加了一個validate_name方法,做爲name字段的自定義行內驗證器,它將在驗證name字段時和其餘驗證函數一塊兒調用。在這個驗證方法中,咱們使用字段的值(field.data)做爲name列的參數值進行查詢,若是查詢到已經存在同名記錄,那麼久爆出ValidationError異常,傳遞錯誤消息做爲參數。

 

四、評論表單

用於建立評論的CommentForm表單類的實現以下所示:

 

personalBlog/forms.py: 評論表單

 

from wtforms import TextAreaField
from wtforms.validators import Email, URL, Length, Optional

class CommentForm(FlaskForm):
    author = StringField('Name', validators = [DataRequired(), Length(1, 30)])
    email = StringField('Email', validators = [DataRequired(), Email(), Length(1, 254)])
    site = StringField('Site', validators = [Optional(), URL(), Length(0, 255)])
    body = TextAreaField('Comment', validators = [DataRequired()])
    submit = SubmitField()

 

在這個表單中,email字段使用了用於驗證電子郵箱地址的Email驗證器。另外,由於評論者的站點是能夠留空的字段,因此咱們使用Optional驗證器來使字段能夠爲空。site字段使用URL驗證器確保輸入的數據爲有效的URL。

 

由於site字段能夠爲空,因此一併附加的Length驗證器的最小長度須要設爲0。

 

和匿名用戶的表單不一樣,管理員不須要填寫諸如姓名、電子郵箱等字段。咱們單獨爲管理員建立了一個表單類,這個表單類繼承自CommentForm類,以下所示:

personalBlog/forms.py:管理員的評論表單

 

from wtforms import HiddenField

class AdminCommentForm(CommentForm):
    author = HiddenField()
    email = HiddenField()
    site = HiddenField()

 

在這個表單中,姓名、Email、站點字段使用HiddenField類從新定義。這個類型表明隱藏字段,即HTML中的<input type=」hidden」>。

 

在模板中手動渲染表單時,咱們可使用Flask-WTF爲表單添加的hidden_tag()方法來渲染全部隱藏字段,而不用逐個調用三個屬性。另外,hidden_tag()方法會一併渲染CSRF令牌字段,所以不用在手動調用csrf_token屬性。

相關文章
相關標籤/搜索