flask使用WTForms进行表单验证

本文介绍了一个基于Flask框架的电影网站后台管理系统登录模块的实现过程,包括前端页面设计、后端视图函数编写、表单验证及CSRF保护等关键技术点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先在pycharm中安装Flask-WTF

登录的前端代码:

login.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>电影网站后台管理系统</title>
    <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
    <link rel="shortcut icon" href="{{ url_for('static',filename='base/images/logo.png')}}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/bootstrap/css/bootstrap.min.css')}}">
    <link rel="stylesheet" href="{{ url_for('static',filename='fonts/css/font-awesome.min.css')}}">
    <link rel="stylesheet" href="{{ url_for('static',filename='ionicons/css/ionicons.min.css')}}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/dist/css/AdminLTE.min.css')}}">
    <link rel="stylesheet" href="{{ url_for('static',filename='admin/plugins/iCheck/square/blue.css')}}">
</head>
<body class="hold-transition login-page">
<div class="login-box">
    <div class="login-logo">
        <a href=""><b>电影网站后台管理系统</b></a>
    </div>
    <div class="login-box-body">
          {% for msg in get_flashed_messages() %}
        <p class="login-box-msg" style="color: red;">{{ mag }}</p>
          {% endfor %}
        <form  method="POST" id="form-data">
            <div class="form-group has-feedback">
                  {{ form.account }}
                <span class="glyphicon glyphicon-envelope form-control-feedback"></span>
{#                错误信息打印#}
                {% for err in form.account.errors %}
                <div class="col-md-12">
                  <font style="color:red">{{ err }}</font>
                </div>
                {% endfor %}
            </div>
            <div class="form-group has-feedback">
                  {{ form.pwd }}
                <span class="glyphicon glyphicon-lock form-control-feedback"></span>
{#                 错误信息打印#}
                {% for err in form.pwd.errors %}
                <div class="col-md-12">
                  <font style="color:red">{{ err }}</font>
                </div>
                {% endfor %}
            </div>
            <div class="row">
                <div class="col-xs-8">
                </div>
                <div class="col-xs-4">
                   {{ form.submit }}
                    {#伪装保护#}
                    {{ form.csrf_token }}
                </div>
            </div>
        </form>
    </div>
</div>
<script src="{{ url_for('static',filename='admin/plugins/jQuery/jQuery-2.2.0.min.js')}}"></script>
<script src="{{ url_for('static',filename='admin/bootstrap/js/bootstrap.min.js')}}"></script>
<script src="{{ url_for('static',filename='admin/plugins/iCheck/icheck.min.js')}}"></script>
</body>
</html>

 这时候通过查看登录页面的网页源代码发现模板都显示出来了,如下所示:

视图views.py

# coding=utf-8
from . import admin
from flask import render_template, redirect, url_for, flash, session, request
from app.admin.forms import LoginForm
from app.models import Admin
from functools import wraps


# 装饰器,访问控制
def admin_login_req(f):
    @wraps(f)
    def decorated_function(*args, **kwargs):
        if "admin" not in session:
            return redirect(url_for("admin.login"))
        return f(*args, **kwargs)

    return decorated_function


# 后台首页
@admin.route("/")
@admin_login_req
def index():
    return render_template("admin/index.html")


# 管理员登录后台
@admin.route("/login/", methods=["GET", "POST"])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        data = form.data
        admin = Admin.query.filter_by(name=data["account"]).first()
        if not admin.check_pwd(data["pwd"]):
            # 消息闪现
            flash("密码错误! ")
            return redirect(url_for("admin.login"))
        session["admin"] = data['account']
        return redirect(request.args.get("next") or url_for("admin.index"))
    return render_template("admin/login.html", form=form)


# 管理员登出
@admin.route("/logout/")
@admin_login_req
def logout():
    session.pop("admin", None)
    return redirect(url_for("admin.login"))

表单forms.py

# coding=utf-8
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired,ValidationError
from app.models import Admin


class LoginForm(FlaskForm):
    """管理员登录表单"""
    account = StringField(
        label="账号",
        validators=[
            DataRequired("请输入账号! ")
        ],
        description="账号",
        render_kw={
            "class": "form-control",
            "placeholder": "请输入账号!",
            "required": "required"
        }
    )

    pwd = PasswordField(
        label="密码",
        validators=[
            DataRequired("请输入密码! ")
        ],
        description="密码",
        render_kw={
            "class": "form-control",
            "placeholder": "请输入密码!",
            "required": "required"
        }
    )
    submit = SubmitField(
        '登录',
        render_kw={
            "class": "btn btn-primary btn-block btn-flat",
        }
    )
    def validate_account(self,field):
        account = field.data
        admin = Admin.query.filter_by(name=account).count()
        if admin == 0:
            raise ValidationError("账户不存在! ")


 

 csrf验证,详情见flask官方文档的CSRF保护这一节,http://docs.jinkan.org/docs/flask-wtf/csrf.html

app.config['SECRET_KEY'] = '2e798784ab164b89a3bbd69683332e18'

SECRET_KEY这里用通用唯一识别码uuid来充当

初始化 __init__.py

# coding=utf-8
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
import pymysql

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:19981028@localhost:3306/movie?charset=utf8'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
app.config['SECRET_KEY'] = '2e798784ab164b89a3bbd69683332e18'
app.debug = True
db = SQLAlchemy(app)  # 实例化

from app.home import home as home_blueprint
from app.admin import admin as admin_blueprint

app.register_blueprint(home_blueprint)
app.register_blueprint(admin_blueprint, url_prefix="/admin")


# 404出错页面
@app.errorhandler(404)
def page_not_found(error):
    return render_template("home/404.html"), 404

模型models.py:

# 管理员
class Admin(db.Model):
    __tablename__ = "admin"
    id = db.Column(db.Integer, primary_key=True)  # 编号
    name = db.Column(db.String(100), unique=True)  # 管理员账号
    pwd = db.Column(db.String(100))  # 管理员密码
    is_super = db.Column(db.SmallInteger)  # 是否是超级管理员,0为超级管理员,1不是
    role_id = db.Column(db.Integer, db.ForeignKey('role.id'))  # 所属角色
    addtime = db.Column(db.DateTime, index=True, default=datetime.now)  # 添加时间
    # adminlogs = db.relationship("Adminlog", backref='admin')  # 管理员登录日志外键关联
    # oplogs = db.relationship("Oplog", backref='admin')  # 管理员操作日志外键关联

    def __repr__(self):
        return "<Admin %r>" % self.name

    def check_pwd(self,pwd):
        from werkzeug.security import check_password_hash
        return check_password_hash(self.pwd,pwd)

可以发现,在以上所有操作以后,视图里面加了装饰器,进行访问控制.退出登录以后,依然可以进入后台的某些页面,这是因为浏览器网页session的原因.浏览器默认保留了session,只要在设置里面清理掉这段时间的session值就会发现不能进入后台模块了,这时候必须再次登录才行,这样就完成了访问权限控制. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值