美文网首页
Python flask 学习笔记(三)

Python flask 学习笔记(三)

作者: 酷酷滴小爽哥 | 来源:发表于2018-12-10 17:12 被阅读0次

    一、Web 表单

    本小节主要讲解了以下内容:

    • WTForms 表单类
    • 常见的 HTML 标准字段
    • 表单的渲染

    test_form.py 这里的 render_template 可以到 form.html 也可以到 form2.html

    from flask import Flask, render_template
    
    from forms import LoginForm
    
    app = Flask(__name__)
    
    @app.route('/')
    def login():
        form = LoginForm()
        return render_template('form2.html', form=form)
    
    
    app.config['SECRET_KEY'] = 'A RANDOM STRING'
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    forms.py

    """
    表单类
    参考文档:http://wtforms.readthedocs.io/en/latest/
    
    字段类型            说明
    StringField         文本字段
    TextAreaField       多行文本字段
    PasswordField       密码文本字段
    HiddenField         隐藏文本字段
    DateField           文本字段,值为datetime.date格式
    DateTimeField       文本字段,值为datetime.datetime格式
    IntegerField        文本字段,值为整数
    DecimalField        文本字段,值为decimal.Decimal
    FloatField          文本字段,值为浮点数
    BooleanField        复选框,值为True和False
    RadioField          一组单选框
    SelectField         下拉列表
    SelectMultipleField 下拉列表,可选择多个值
    FileField           文件上传字段
    SubmitField         表单提交按钮
    FormField           把表单作为字段嵌入另一个表单
    FieldList           一组指定类型的字段
    
    """
    from flask_wtf import FlaskForm
    from wtforms import StringField, SubmitField, SelectField, RadioField, \
    TextAreaField, DateField, BooleanField
    from wtforms.validators import DataRequired
    from wtforms.widgets import CheckboxInput, PasswordInput
    
    # 表单类
    class LoginForm(FlaskForm):
        # DataRequired 设置必需填写;render_kw 为对应标签的属性设置参数
        username = StringField(label='用户名', validators=[DataRequired()], 
            description="请输入用户名",
            render_kw={"required": "required", "class": "这是选择器"}
            )
        password = StringField('密码', validators=[DataRequired()], widget=PasswordInput())
        language = RadioField('编程语言',choices=[('cpp','C++'), ('py','Python')])
        code = TextAreaField('代码')
        date = DateField('日期', render_kw={"type" : "date"})
        is_checked = BooleanField('是否已经通过验证')
        submit = SubmitField('登录')
    

    form.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>form</title>
    </head>
    <body>
        <form>
            <div>
                {# 通过 (id="id-username") 可以设置对应标签的属性参数 #}
                {{ form.username.label }} : {{ form.username(id="id-username")}}
                <small>{{ form.username.description }}</small>
            </div>
            <div>
                {{ form.password.label }} : {{ form.password }}
            </div>
            <div>
                {{ form.language.label }}
                {% for radio in form.language %}
                <label>{{ radio }} {{ radio.label.text }}</label>
                {% endfor %}
            </div>
            <div>
                {{ form.code.label }} : {{ form.code }}
            </div>
            <div>
                {{ form.date.label }} : {{ form.date }}
            </div>
            <div>
                {{ form.is_checked.label }} : {{ form.is_checked }}
            </div>
            <div>
                {{ form.submit.label }} : {{ form.submit }}
                {# 注意这里的csrf #}
                {{ form.csrf_token }}
            </div>
        </form>
    </body>
    </html>
    

    form2.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>form2</title>
    </head>
    <body>
        <form action="." method="get" accept-charset="utf-8">
            {% for field in form %}
                {# 如果是隐藏表单域,则不显示label #}
                {% if field.type in ['CSRFTokenField', 'HiddenField'] %}
                    {{ field }}
                {% else %}
                <div>
                    {{ field.label }} : {{ field }}
                </div>
                {% endif %}
            {% endfor %}
        </form>
    </body>
    </html>
    

    二、表单的处理

    • Form 内置函数的使用
    • POST
    • GET
    • FILES

    直观上来说 GET 方式:
    好处:分享链接后,别人打开的和你打开的一样
    坏处:你的值在链接里,不够隐私

    GET POST 方式异同:

    • GET在浏览器回退时是无害的,而POST会再次提交请求。
    • GET产生的URL地址可以被Bookmark,而POST不可以。
    • GET请求会被浏览器主动cache,而POST不会,除非手动设置。
    • GET请求只能进行url编码,而POST支持多种编码方式。
    • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
    • GET请求在URL中传送的参数是有长度限制的,而POST么有。
    • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
    • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
    • GET参数通过URL传递,POST放在Request body中。

    test_regitst.py

    import os
    
    from flask import Flask, render_template, request
    
    from forms import RegistForm, UploadForm
    
    app = Flask(__name__)
    
    
    # 文件上传目录 os.path.dirname(__file__) 指代当前文件路径,后面加个 medias 指的是,当前路径下的 medias 目录
    UPLOAD_PATH = os.path.join(os.path.dirname(__file__), 'medias')
    
    
    @app.route('/regist/', methods=['GET', 'POST'])
    def regist():
        form = RegistForm()
        if form.validate_on_submit():
            data = form.data
            print(data)
        return render_template('regist.html', form=form)
    
    
    @app.route('/upload/', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        if form.validate_on_submit():
            print(request.files['image'])
            image = form.data['image']
            if image:
                print(image.filename)
                filename = os.path.join(UPLOAD_PATH, image.filename)
                print(filename)
                image.save(filename)
                flash("文件上传成功")
                return 'success!'
            else:
                return 'no file'
        else:
            print(form.errors)
        return render_template('upload.html', form=form)
    
    
    app.config['SECRET_KEY'] = 'A RANDOM STRING'
    
    if __name__ == '__main__':
        app.run(debug=True)
    

    forms.py

    需要注意的是 validators 方式是进行后台的验证,而设置 required 的方式或者使用 JavaScript 的方式,只是前端的方式,前端的方式是可以绕过去的。

    from flask_wtf import FlaskForm
    from wtforms import StringField, SubmitField, SelectField, RadioField, \
    TextAreaField, DateField, BooleanField, PasswordField, FileField
    from wtforms.validators import DataRequired
    from wtforms.widgets import CheckboxInput, PasswordInput
    
    from validator import passwordValid
    
    class LoginForm(FlaskForm):
        username = StringField(label='用户名', validators=[DataRequired()], 
            description="请输入用户名",
            render_kw={"required": "required", "class": "这是选择器"}
            )
        password = StringField('密码', validators=[DataRequired()], widget=PasswordInput())
        language = RadioField('编程语言',choices=[('cpp','C++'), ('py','Python')])
        code = TextAreaField('代码')
        date = DateField('日期', render_kw={"type" : "date"})
        is_checked = BooleanField('是否已经通过验证')
        submit = SubmitField('登录')
    
    
    class RegistForm(FlaskForm):
        username = StringField('用户名', validators=[DataRequired()],
            render_kw={'required': 'required', 'placeholder': '请输入用户名'},
            description='输入邮箱进行注册'
        )
        password = PasswordField('密码', validators=[DataRequired('请输入密码'), passwordValid])
        language = RadioField('编程语言', choices=[('cpp','C++'), ('py','Python')])
    
    
    
    class UploadForm(FlaskForm):
            image = FileField('文件上传', validators=[DataRequired()],
                render_kw={'required': 'required', 'class': 'form-control'}
            )
    

    validator.py

    from wtforms.validators import ValidationError
    
    def passwordValid(form, field):
        password = field.data
        if len(password) != 6:
            raise ValidationError('密码必须是6位')
        if not password.isdigit():
            raise ValidationError('密码必须是数字')
        return password
    

    regist.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>regist</title>
        <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css', _external=True)}}">
    </head>
    <body>
        <div class="container">
            {% for message in get_flashed_messages() %}
            <div class="alert alert-warning">
                <button type="button" class="close" data-dismiss='alert'>&times;</button>
                {{ message }}
            </div>
            {% endfor %}
            <div class="col-md-6">
                <form method="POST" action=".">
                    <hr>
                    {{ form.username.label }} {{ form.username }}
                    <hr>
                    {{ form.password.label }} {{ form.password }}
                    <hr>
                    {{ form.language.label }} {{ form.language }}
                    <hr>
                    <b>
                    {% if form.password.errors %}
                    {{ form.password.errors }}
                    {% endif %}
                    </b>
                    <hr>
                    {{ form.csrf_token }}
                    <button type="submit">提交</button>
                </form>
            </div>
        </div>
        <script type="text/javascript" src="{{ url_for('static', filename='jquery.1.10.2.min.js', _external=True) }}"></script>
        <script type="text/javascript" src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js', _external=True) }}"></script>
    </body>
    </html>
    

    upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>upload</title>
        <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='bootstrap/css/bootstrap.min.css', _external=True) }}">
    </head>
    <body>
        <div class="container">
            <div class="col-md-6">
                <form action=".", method="post", enctype="multipart/form-data">
                    <hr>
                    {{ form.image.label }}
                    <hr>
                    {{ form.image }}
                    <hr>
                    {{ form.csrf_token }}
                    <hr>
                    <button type="submit">上传</button>
                </form>
            </div>
        </div>
        <script type="text/javascript" src="{{ url_for('static', filename='jquery.1.10.2.min.js', _external=True)}}"></script>
        <script type="text/javascript" src="{{ url_for('static', filename='bootstrap/js/bootstrap.min.js', _external=True) }}"></script>
    </body>
    </html>
    

    相关文章

      网友评论

          本文标题:Python flask 学习笔记(三)

          本文链接:https://www.haomeiwen.com/subject/uwnhhqtx.html