BZ易风

导航

 

安装deform

pip install pyramid_deform
pip install js.deform

deform表单库介绍

与pyramid同属Pylons Project表单库

Colander:定义表单结构

Peppercom:序列化和反序列化

Chameleon:模板引擎

development.ini里导入pyramid_deform

[app:main]
use = egg:MyShop

pyramid.reload_templates = true
pyramid.debug_authorization = true
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
pyramid.includes =
    pyramid_debugtoolbar
    pyramid_tm
    pyramid_layout
    pyramid_deform

创建lib/deforms.py文件

# -*- coding:UTF-8 -*-
import colander
import deform
from js.deform import deform as deform_static

class LoginFormSchema(colander.MappingSchema):  # 定义一个LoginFormSchema表单结构 MappingSchema表示一个映射类型
    username = colander.SchemaNode(colander.Str())  # colander.SchemaNode相当于定义的Column
    password = colander.SchemaNode(colander.Str(),
                                   widget=deform.widget.PasswordWidget()  # 使密码密文显示
                                   )
    email = colander.SchemaNode(colander.Str(),
                                validator=colander.Email()  # 验证器 验证邮箱是否合法
                                )

 

在需要的视图views里导入

如login.py中

# -*- coding:UTF-8 -*-
from pyramid.response import Response
from pyramid.view import view_config, view_defaults
from pyramid.httpexceptions import HTTPFound, HTTPBadRequest, HTTPServerError, \
    HTTPForbidden, HTTPUnauthorized
from pyramid.security import remember, forget
from myshop.lib import category, user, deforms
from base import CBase

ctrl = 'login'

# @view_config(route_name='home', renderer='templates/mytemplate.pt')
@view_defaults(route_name='/')
class login(CBase):
    def __init__(self, request):
        CBase.__init__(self, request)
        self.request.title = u'登录'

    @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                 renderer="login.html")
                 # renderer="string")
    def view(self):
        deforms.deform_static.need()  # 使用deform必须步骤
        schema = deforms.LoginFormSchema()  # 声明一个schema
        # 声明一个表单
        form = deforms.deform.Form(schema,
                                   buttons=('submit',))  # 表单上需要哪些按钮
 
        return {
            'title':'login',
            'form':form.render(),  #显示表单
        }

模板login.html中显示声明的表单

<%inherit file="layout/login_base.html"/>
<%block name="log_c">
    <div class="log_c">
        ${form | n}
    </div>
</%block>

显示如下:

 后台验证表单

# -*- coding:UTF-8 -*-
from pyramid.response import Response
from pyramid.view import view_config, view_defaults
from pyramid.httpexceptions import HTTPFound, HTTPBadRequest, HTTPServerError, \
    HTTPForbidden, HTTPUnauthorized
from pyramid.security import remember, forget
from myshop.lib import category, user, deforms
from base import CBase

ctrl = 'login'

# @view_config(route_name='home', renderer='templates/mytemplate.pt')
@view_defaults(route_name='/')
class login(CBase):
    def __init__(self, request):
        CBase.__init__(self, request)
        self.request.title = u'登录'

    @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                 renderer="login.html")
                 # renderer="string")
    def view(self):
        deforms.deform_static.need()  # 使用deform必须步骤
        schema = deforms.LoginFormSchema()  # 声明一个schema
        # 声明一个表单
        form = deforms.deform.Form(schema,
                                   buttons=('submit',))  # 表单上需要哪些按钮

        if 'submit' in self.request.POST:
            try:
                appstruct = form.validate(self.request.POST.items())  # 对用户提交的内容进行有效性验证
            except deforms.deform.ValidationFailure, e:
                return {
                    'title':'login',
                    'form':e.render()  # 如果校验失败会提示错误信息
                }
            user_info = user.get_user_by_name(name=appstruct['username'])  # appstruct['username'] 获取表单的username
            if not user_info:
                return {
                    'title': 'login',
                    'form': form.render(),
                }
            if user_info.password != appstruct['password']:  # 获取form传过来的密码
                return {
                    'title': 'login',
                    'form': form.render(),
                }
            headers = remember(self.request, user_info.id)
            return HTTPFound(location='/', headers=headers)

        return {
            'title':'login',
            'form':form.render(),  #显示表单
        }

 自定义验证器验证

1.用户名验证--字段级别验证 node

自定义验证器lib/validators.py

# -*- coding:UTF-8 -*-
import colander
import deform
from myshop.lib import user

def username_validator(node, value):
    user_info = user.get_user_by_name(name=value)
    if not user_info:
        raise colander.Invalid(node, u'用户名%s不存在' % value)

deforms.py中导入验证器

# -*- coding:UTF-8 -*-
import colander
import deform
from js.deform import deform as deform_static
import validators

class LoginFormSchema(colander.MappingSchema):  # 定义一个LoginFormSchema表单结构 MappingSchema表示一个映射类型
    username = colander.SchemaNode(colander.Str(),  # colander.SchemaNode相当于定义的Column
                                   validator = validators.username_validator  # 用自定义的验证器验证数据
                                   )

视图函数login.py中验证用户是否存在可以删除了,在验证器中验证

        if 'submit' in self.request.POST:
            try:
                appstruct = form.validate(self.request.POST.items())  # 对用户提交的内容进行有效性验证
            except deforms.deform.ValidationFailure, e:
                return {
                    'title':'login',
                    'form':e.render()  # 如果校验失败会提示错误信息
                }
            user_info = user.get_user_by_name(name=appstruct['username'])
            # if not user_info:
            #     return {
            #         'title': 'login',
            #         'form': form.render(),
            #     }

2.密码验证--表单级别验证 form

lib/validators.py声明一个password_validator

def password_validator(form, value):
    username = value['username']
    password = value['password']
    user_info = user.get_user_by_name(name=username)
    if user_info.password != password:
        raise colander.Invalid(form, u'用户名密码不正确')

视图函数login.py中声明Schema对象时应用表单验证

# -*- coding:UTF-8 -*-
from pyramid.response import Response
from pyramid.view import view_config, view_defaults
from pyramid.httpexceptions import HTTPFound, HTTPBadRequest, HTTPServerError, \
    HTTPForbidden, HTTPUnauthorized
from pyramid.security import remember, forget
from myshop.lib import category, user, deforms, validators
from base import CBase

ctrl = 'login'

# @view_config(route_name='home', renderer='templates/mytemplate.pt')
@view_defaults(route_name='/')
class login(CBase):
    def __init__(self, request):
        CBase.__init__(self, request)
        self.request.title = u'登录'

    @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                 renderer="login.html")
                 # renderer="string")
    def view(self):
        deforms.deform_static.need()  # 使用deform必须步骤
        schema = deforms.LoginFormSchema(validator=validators.password_validator)  # 声明一个schema   # validator指定表单级别验证
        # 声明一个表单
        form = deforms.deform.Form(schema,
                                   buttons=('submit',),  # 表单上需要哪些按钮

                                   )

        if 'submit' in self.request.POST:
            try:
                appstruct = form.validate(self.request.POST.items())  # 对用户提交的内容进行有效性验证
            except deforms.deform.ValidationFailure, e:
                return {
                    'title':'login',
                    'form':e.render()  # 如果校验失败会提示错误信息
                }

 此上不难看出,重复查询user_info的次数过多,如何能一次查询多次使用

定义TypeUser(),这里我直接在lib/deforms.py中定义了 也可以另写

# -*- coding:UTF-8 -*-
import colander
import deform
from js.deform import deform as deform_static
import validators

from myshop.models import User
from myshop.lib import user

class TypeUser(object):
    def serialize(self, node, appstruct):  # 序列化给表单
        if appstruct is colander.null:  # 固定用法,如果colander为null 则返回null
            return colander.null
        if not isinstance(appstruct, User):  # 判断appstruct类型与数据库的User类型是否相同
            raise colander.Invalid(node, u'用户类型%r不正确' % appstruct)
        return appstruct.name
    def deserialize(self, node, cstruct):  # 表单反序列化给后台
        if cstruct is colander.null:
            return colander.null
        if not isinstance(cstruct, basestring):
            raise colander.Invalid(node, u'用户%r格式不正确' % cstruct)

        user_info = user.get_user_by_name(name=cstruct)
        if not user_info:
            raise colander.Invalid(node, u'用户%s不存在' % cstruct)
        return user_info

这样appstruct['username']就是user_info数据了

validators.py中密码验证要改动

def password_validator(form, value):
    user_info = value['username']
    password = value['password']
    # user_info = user.get_user_by_name(name=username)  # 如果自定义TypeUser的话 不需要多次查询数据库
    if user_info.password != password:
        raise colander.Invalid(form, u'用户名密码不正确')

同理,login.py中查询user数据也可以删掉了

 @view_config(match_param=('ctrl=%s' % ctrl, 'action=view'),
                 renderer="login.html")
                 # renderer="string")
    def view(self):
        deforms.deform_static.need()  # 使用deform必须步骤
        schema = deforms.LoginFormSchema(validator=validators.password_validator)  # 声明一个schema   # validator指定表单级别验证
        # 声明一个表单
        form = deforms.deform.Form(schema,
                                   buttons=('submit',),  # 表单上需要哪些按钮
                                   )

        if 'submit' in self.request.POST:
            try:
                appstruct = form.validate(self.request.POST.items())  # 对用户提交的内容进行有效性验证
            except deforms.deform.ValidationFailure, e:
                return {
                    'title':'login',
                    'form':e.render()  # 如果校验失败会提示错误信息
                }
            # user_info = user.get_user_by_name(name=appstruct['username'])
            user_info = appstruct['username']  # 直接把user数据赋值给user_info
            headers = remember(self.request, user_info.id)
            return HTTPFound(location='/', headers=headers)

 OK 跟之前一样登录

posted on 2020-02-07 21:58  BZ易风  阅读(351)  评论(0编辑  收藏  举报