美文网首页
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