zoukankan      html  css  js  c++  java
  • wtforms 使用



    wtforms是一个表单模板库, 下面以修改密码表单为例简单说明其用法.
    我们可以用python代码定义form的基本元素, 比如用户名/邮箱, 并给定各个元素的validation条件.

    然后在render_template()方法中, 将python的form类传递给html模板. 在模板上, 需要有placeholder来接纳python传过来的form元素.


    使用wtforms的好处是:
    1. form验证可以使用python来做, 不必将验证代码放到javascript中.
    2. 在python视图函数中, 可以很方便地获取表单元素, 比如使用form.username.data, 即可获取表单上的username值.
    3. 可以简化html模板的设计. 采用Flask-Bootstrap 扩展或者使用一些jinja2 marco都能简化html代码.
    4. 更重要的好处是, 将validation逻辑从表现层中解耦

     
    下面仅讲解wtforms和bootstrap的结合使用, 而不涉及wtforms的基本用法.

    bear-z写的bootstrap的macro
    http://bear-z.com/python/render-bootstrap-3-forms-with-wtforms-and-jinja/


    wtforms和bootstrap结合使用的详解
    http://pythonthusiast.pythonblogs.com/230_pythonthusiast/archive/1315_flask_biography_tutorial_part_vi__adding_sign_up_form_using_bootstrap_3_and_flask-wtf.html


    Flask-Bootstrap的简单用法
    1. 安装Flask-Bootstrap后, 将Flask-Bootstrap的bootstrap模板目录放在我们自己的templates目录下, 即形成一个二级子目录.
    2. 将flask的app做封装
        from flask_bootstrap import Bootstrap
        Bootstrap(app)
    3. 定义python的一个WTF form类, 比如 MyForm
    4. 在flask的view函数中, 将MyForm实例传到模板html中,  即render_template('MyForm.html',form=MyForm())
    5. 在MyForm.html模板中, 引入flask_bootstrap的wtf macro文件, 最简单的方法是wtf.quick_form(), 即可将 MyForm python类定义的所有元素渲染到html上.  
      {% import "bootstrap/wtf.html" as wtf %}
      ....
        <div>         
            {{ wtf.quick_form(form, id="myform", form_type="horizontal", horizontal_columns=('sm', 2, 5)) }}
            <!-- 上面horizontal_columns()后两个参数是用来标示每一行的label和textbox的宽度 -->
        </div>


    Flask-Bootstrap的quick_form()生成的html往往只适用于简单的排版, 所以比较适合做demo. 即使直接用wtf.form_field()来渲染每个元素, 也没有办法指定css class, 灵活度不高. 不过, 我们可提取出Flask-Bootstrap生成的html样式, 做为下一步美化的基础.


    bear-z写的bootstrap的macro, 和Flask-Bootstrap相比, 灵活度高一些, 可以通过class_参数为每个元素指定css class.
    {% import "bootstrap/bearz_wtf.html" as wtf2 %}
    {{ wtf2.render_field(form.email, label_visible=false, placeholder='userID', type='email',class_='col-md-8') }}


    涉及到表单提交, flask视图函数其实都是一个样子. 先看请求类型, 如是POST, 验证form上的数据, 验证通过则更新, 不通过则返回到原来的Form. 如请求是GET, 则表明是新的请求, 初始化一个新的Form, 并做html渲染.

    下面是一个更新密码的示例.

    ##############################################
    #flask view 模块
    ##############################################
    @mod.route('/MyApp/updatePwd/', methods=['GET','POST'])
    def udpatePwd():
        if request.method == 'POST':  # construct WTF form object based on request data
            form = UserPwdForm(request.form)
            if form.validate():       # WTForm validation OK
                user=User.getUser(form.EMPNO.data)
                aborted=False
                if user is None:
                    aborted=True
                    form.EMPNO.errors.append('This EmpNo does not exist.')
                if not aborted and not User.checkUserPwd(form.EMPNO.data, form.PWD.data):
                    aborted=True    
                    form.PWD.errors.append('Old password is not correct.')
                if aborted:
                    return _navigateToUpdatePwd(form)  # return the page with error message
                else:  # all validation OK
                    try:
                        User.updatePassword(form.EMPNO.data,form.NewPWD.data)
                        return _navigateSuccessfulPage()
                    except Exception as e:
                        return _navigateErrorPage(logger=current_app.logger, exception=e)
            else:  # validation failed
                return _navigateToUpdatePwd(form)         
            
        else:  # GET request
            return _navigateToUpdatePwd(UserPwdForm())
     
     
    def _navigateToUpdatePwd(form):
        return render_template("form_update_pwd.html",  
                                form=form,
                                )     


    def _navigateSuccessfulPage():
        return render_template("form_successful.html",  
                                )      
                       
                       
    def _navigateErrorPage(logger, friendlyErrorMsg=None, exception=None):
        if exception:
            msg='%s'%exception
            tracebackInfo=traceback.format_exc()
            tracebackInfo=tracebackInfo.replace(chr(10), '<br>')
            tracebackInfo=tracebackInfo.replace(chr(13), '<br>')

        if friendlyErrorMsg:
            msg=friendlyErrorMsg
            
        logger.error(msg)    
        if exception:
            logger.exception(exception)  
       
        #output the msg highlighted in danger  
        flash(msg, 'error')
        return render_template("form_error.html",  
                                tracebackInfo=tracebackInfo
                                )     
                           
                           
                       

    ##############################################                            
    #flask form 模块
    ##############################################
    from flask_wtf import Form
    from wtforms import StringField, PasswordField, SubmitField
    from wtforms.validators import DataRequired, EqualTo, Length, InputRequired
    from wtforms.fields.simple import PasswordField

    class UserPwdForm(Form):
        
        EMPNO=StringField('Emp No',validators=[
            DataRequired('Please enter Emp No'),
            Length(min = 1, max = 20,message='length must between 1 and 20')
        ])
        
        PWD=PasswordField('Old password',validators=[
            DataRequired('Please enter old password'),
        ])    
            
        NewPWD=PasswordField('New password',validators=[
            DataRequired('Please enter new password'),
        ])    
        
        RptNewPWD=PasswordField('Confirm new password',validators=[
            DataRequired('Please confirm new password again'),
            EqualTo('NewPWD','Password must be match')
        ])        
            
        submit = SubmitField('Submit')    


        
        
    ##############################################    
    # html文件 form_update_pwd.html    
    ##############################################
    {% if not is_xhr|default(false) %}{% extends "report_base.html" %}{% endif %}
    {% import "bootstrap/wtf.html" as wtf %}
    {% import "bootstrap/bearz_wtf.html" as wtf2 %}                    


    {% block other_head_javascript %}
        <script src="/static/js/jquery.min.js"></script>
    {% endblock %}

     
    {% block content %}
     
          <h1>Update password</h1>
         
           <div>         
               {{ wtf.quick_form(form, id="FormUpdatePwd", form_type="horizontal", horizontal_columns=('sm', 2, 5)) }}
           </div>
     
            
    {% endblock %}



    ##############################################
    # html文件 form_successful.html
    ##############################################
    {% if not is_xhr|default(false) %}{% extends "report_base.html" %}{% endif %}
    {% import "bootstrap/wtf.html" as wtf %}
    {% import "bootstrap/bearz_wtf.html" as wtf2 %}
                         

    {% block other_head_javascript %}
        <script src="/static/js/jquery.min.js"></script>
    {% endblock %}

     
    {% block content %}
     
    <h1>Updated successfully.</h1>
            
    {% endblock %}

     


    理解session和cookie
    http://lucindabfls.blog.163.com/blog/static/1247404702010326103548751/
    http://hqhou.blog.163.com/blog/static/852039352013431033327/
  • 相关阅读:
    疫情数据背后,聊聊数据分析平台变迁史
    华为五大专家亲述:如何转型搞 AI?
    【华为云技术分享】LwM2M协议的学习与分享
    Spring5参考指南: BeanWrapper和PropertyEditor
    Spring5参考指南: Resources
    Spring5参考指南:事件Event
    Spring5参考指南:Environment
    Spring5参考指南:JSR 330标准注解
    Spring5参考指南:组件扫描
    Spring5参考指南:基于注解的容器配置
  • 原文地址:https://www.cnblogs.com/harrychinese/p/wtforms.html
Copyright © 2011-2022 走看看