前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python 系列文章 —— flask 表单案例

Python 系列文章 —— flask 表单案例

原创
作者头像
玩转编程
发布2022-01-13 11:05:22
5280
发布2022-01-13 11:05:22
举报
文章被收录于专栏:玩转编程玩转编程
  • app.py
代码语言:javascript
复制
from flask import Flask, render_template, redirect, url_for, request

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, EqualTo

from werkzeug.security import generate_password_hash
from werkzeug.security import check_password_hash

from flask_login import LoginManager, UserMixin, current_user
from flask_login import logout_user, login_user, login_required

import uuid


app = Flask(__name__)  # 创建 Flask 应用

app.secret_key = 'abc'  # 设置表单交互密钥

login_manager = LoginManager()  # 实例化登录管理对象
login_manager.init_app(app)  # 初始化应用
login_manager.session_protection = 'strong'
login_manager.login_view = 'login'  # 设置用户登录视图函数 endpoint

# 用户数据
USERS = [
    {
        "id": 1,
        "name": 'lily',
        "password": generate_password_hash('123')
    },
    {
        "id": 2,
        "name": 'tom',
        "password": generate_password_hash('123')
    }
]

def create_user(user_name, password):
    """创建一个用户"""
    user = {
        "name": user_name,
        "password": generate_password_hash(password),
        "id": uuid.uuid4()
    }
    USERS.append(user)

def get_user(user_name):
    """根据用户名获得用户记录"""
    for user in USERS:
        if user.get("name") == user_name:
            return user
    return None

class LoginForm(FlaskForm):
    """登录表单类"""
    username = StringField('用户名', validators=[DataRequired()])
    password = PasswordField('密码', validators=[DataRequired()])

class SignupForm(FlaskForm):
    """用户注册表单类"""
    username = StringField('用户名', validators=[DataRequired()])
    password = PasswordField('密码', [
        DataRequired(),
        EqualTo('confirm', message='两次输入的密码不一致')
    ])
    confirm = PasswordField('确认密码')

class User(UserMixin):
    """用户类"""
    def __init__(self, user):
        self.username = user.get("name")
        self.password_hash = user.get("password")
        self.id = user.get("id")

    def verify_password(self, password):
        """密码验证"""
        if self.password_hash is None:
            return False
        return check_password_hash(self.password_hash, password)

    def get_id(self):
        """获取用户ID"""
        return self.id

    @staticmethod
    def get(user_id):
        """根据用户ID获取用户实体,为 login_user 方法提供支持"""
        if not user_id:
            return None
        for user in USERS:
            if user.get('id') == user_id:
                return User(user)
        return None

@login_manager.user_loader  # 定义获取登录用户的方法
def load_user(user_id):
    return User.get(user_id)


@app.route('/signup/', methods=('GET', 'POST'))  # 注册
def signup():
    form = SignupForm()
    emsg = None
    if form.validate_on_submit():
        user_name = form.username.data
        password = form.password.data

        user_info = get_user(user_name)  # 用用户名获取用户信息
        if user_info is None:
            create_user(user_name, password)  # 如果不存在则创建用户
            return redirect(url_for("login"))  # 创建后跳转到登录页
        else:
            emsg = "用户名已存在"  # 如果用户已存在则给出错误提示
    return render_template('signup.html', form=form, emsg=emsg)

@app.route('/login/', methods=('GET', 'POST'))  # 登录
def login():
    form = LoginForm()
    emsg = None
    if form.validate_on_submit():
        user_name = form.username.data
        password = form.password.data
        user_info = get_user(user_name)
        if user_info is None:
            emsg = "用户名或密码密码有误"
        else:
            user = User(user_info)
            if user.verify_password(password):
                login_user(user)
                return redirect(request.args.get('next') or url_for('index'))
            else:
                emsg = "用户名或密码密码有误"
    return render_template('login.html', form=form, emsg=emsg)

@app.route('/')  # 首页
@login_required  # 需要登录才能访问
def index():
    return render_template('index.html', username=current_user.username)

@app.route('/logout')  # 登出
@login_required
def logout():
    logout_user()
    return redirect(url_for('login'))

if __name__ == '__main__':
    app.run(debug=True)
  • template
    • index.html
代码语言:txt
复制
```js
代码语言:txt
复制
<h1>欢迎 {{ username }}!</h1>
代码语言:txt
复制
<a href='{{ url_for('logout')}}'>登出</a>
代码语言:txt
复制
```
代码语言:txt
复制
- login
代码语言:txt
复制
```js
代码语言:txt
复制
{% macro render_field(field) %}
代码语言:txt
复制
<dt>{{ field.label }}:
代码语言:txt
复制
<dd>{{ field(**kwargs)|safe }}
代码语言:txt
复制
{% if field.errors %}
代码语言:txt
复制
    <ul class=errors>
代码语言:txt
复制
    {% for error in field.errors %}
代码语言:txt
复制
    <li>{{ error }}</li>
代码语言:txt
复制
    {% endfor %}
代码语言:txt
复制
    </ul>
代码语言:txt
复制
{% endif %}
代码语言:txt
复制
</dd>
代码语言:txt
复制
{% endmacro %}
代码语言:txt
复制
<!-- <a href="{{ url_for('signup') }}">注册</a> -->
代码语言:txt
复制
<form method="POST">
代码语言:txt
复制
    {{ form.csrf_token }}
代码语言:txt
复制
    {{ render_field(form.username) }}
代码语言:txt
复制
    {{ render_field(form.password) }}
代码语言:txt
复制
    {% if emsg %}
代码语言:txt
复制
        <h3> {{ emsg }}</h3>
代码语言:txt
复制
    {% endif %}
代码语言:txt
复制
    <input type="submit" value="登录">
代码语言:txt
复制
</form>
代码语言:txt
复制
```
代码语言:txt
复制
- signup
代码语言:txt
复制
```js
代码语言:txt
复制
{% macro render_field(field) %}
代码语言:txt
复制
<dt>{{ field.label }}:
代码语言:txt
复制
<dd>{{ field(**kwargs)|safe }}
代码语言:txt
复制
{% if field.errors %}
代码语言:txt
复制
    <ul class=errors>
代码语言:txt
复制
    {% for error in field.errors %}
代码语言:txt
复制
    <li>{{ error }}</li>
代码语言:txt
复制
    {% endfor %}
代码语言:txt
复制
    </ul>
代码语言:txt
复制
{% endif %}
代码语言:txt
复制
</dd>
代码语言:txt
复制
{% endmacro %}
代码语言:txt
复制
<form method="POST">
代码语言:txt
复制
    {{ form.csrf_token }}
代码语言:txt
复制
    {{ render_field(form.username) }}
代码语言:txt
复制
    {{ render_field(form.password) }}
代码语言:txt
复制
    {{ render_field(form.confirm) }}
代码语言:txt
复制
    {% if emsg %}
代码语言:txt
复制
        <h3> {{ emsg }}</h3>
代码语言:txt
复制
    {% endif %}
代码语言:txt
复制
    <input type="submit" value="注册">
代码语言:txt
复制
</form>

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档