Python flask 学习笔记(三)

2018-12-10  本文已影响0人  酷酷滴小爽哥

一、Web 表单

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

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>

二、表单的处理

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

GET POST 方式异同:

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>
上一篇下一篇

猜你喜欢

热点阅读