上一章講了如何使用formalchemy+jinja2建立表單,這一章將要講formalchemy在服務器端怎麼對錶單數據驗證。咱們用前面的User表單來進行舉例,User中有幾個地方須要驗證,下面一一列出來: html
以上爲針對User表單須要驗證的內容,驗證需求中的必填/長度限制在formalchemy的validator中已經內建,那麼驗證惟一和驗證兩個password是否相等還須要咱們自定義下驗證方法,這裏是formalchemy關於自定義驗證方法的文檔,下面上這兩個自定義方法的代碼,先在app根目錄下建立一個customValidators.py用於存放自定義的驗證方法。 python
customValidators.py web
#-*- coding: utf-8 -*- from formalchemy import ValidationError #檢驗兩個字段的值是否相等 def customEqual(equal_field, message): def check(value, field): if field.is_required() or (not field.is_required() and value): if getattr(field.parent, equal_field).value != value: raise ValidationError(message) return check #檢驗字段值在數據庫中是否惟一,並可設置是否忽略自身值,這在編輯已有信息的時候驗證惟一很是有用 def customUnique(session, message="此數據已存在", checkSelf=False): def check(value, field): model = field.model.__class__ if checkSelf: query = session.query(model).filter( (getattr(model, field.name)==value) & (model.id!=field.model.id) ).first() else: query = session.query(model).filter(getattr(model, field.name)==value).first() if query: raise ValidationError(message) return check接下來讓咱們修改上一章的forms.py,把驗證信息加入進去。
#-*- coding:utf-8 -*- from formalchemy import config, validators, Field, FieldSet from customEngine import Jinja2Engine from models import * from customValidators import * class UserForm: def __init__(self): #這裏的directories是指表單模板存放的地方,咱們在第二章提到的templates下建立一個文件夾,命名爲form config.engine = Jinja2Engine(directories=["templates/form"]) #爲表單設置label def setLabel(self): self.name = self.fs.name.label("User Name") self.email = self.fs.email.label("Email Address") self.password = self.fs.password.label("Password") self.superuser = self.fs.superuser.label("Admin?") #定義編輯模式下通用的設置,編輯模式包括:新增,修改 def wmode(self, password=None): self.setLabel() #由於新增和修改中都須要用戶從新確認密碼,因此要爲表單加入Confirm Password #若是有指定password的值,說明用戶是在修改記錄,那麼Confirm Password也必須有值 if not password: self.fs.insert_after(self.fs.password, Field("confirm_password")) else: self.fs.insert_after(self.fs.password, Field("confirm_password", value=password)) self.confirm_password = self.fs.confirm_password.label("Re-enter Password") self.name = self.name.required().validate( validators.length(min=6, max=20) ) self.email = self.email.required().email().validate( validators.email ).validate( validators.maxlength(32) ) self.password = self.password.required().password().validate( validators.length(min=6, max=32) ) self.confirm_password = self.confirm_password.required().password().validate( validators.length(min=6, max=32) ).validate( customEqual("password", "密碼先後不一致") ) #定義新增用戶時調用的方法 def write_render(self, cls): #設置Fieldset對象,指定要綁定的sqlalchemy中的表類,並賦予sqlalchemy的session self.fs = FieldSet(User, session=cls.db) self.wmode() #配置表單信息 self.fs.configure( #表單包含的字段 include=[ self.name.validate(customUnique(cls.db)), self.email.validate(customUnique(cls.db)), self.password, self.confirm_password ] ) return self.fs爲了觸發驗證,須要提交表單,咱們爲main.py的showform類添加POST方法,main.py總體修改以下。
main.py sql
#-*- coding:utf-8 -*- import web, middleware from web.contrib.template import render_jinja from models import * from forms import * import sys reload(sys) sys.setdefaultencoding("utf-8") urls = ( "/", "index", "/form/", "showform", ) app = web.application(urls, globals()) app.add_processor(middleware.set_orm) render = render_jinja( 'templates', encoding = 'utf-8', ) class BaseView(object): def __init__(self): #從web.ctx.orm獲取session放入基類的db中 self.db = web.ctx.orm class index(BaseView): def GET(self): return render.index() class showform(BaseView): def __init__(self): super(showform, self).__init__() form = UserForm() self.fs = form.write_render(self) def GET(self): return render.form(form=self.fs) def POST(self): data = web.input() self.fs.rebind(data=data) if self.fs.validate(): self.fs.sync() return "success" return render.form(form=self.fs) if __name__ == "__main__": app.run()下面運行main.py,訪問/form/,用各類不規則的數據提交吧,看看驗證是否都有做用:)