定制设计Python Flask Web:博客登录和注册页面实现代码

文章目录

1. 项目预览

1.1 登录

1.2 注册

2. 定制设计项目目录结构

3. 定制设计项目代码展示

blueprint

init.py

from .user import bp as user_bp
  • 1

forms.py

import wtformsfrom wtforms.validators import length, email, EqualTofrom models import EmailCaptchaModel, UserModelclass LoginForm(wtforms.Form):    email = wtforms.StringField(validators=[email()])    password = wtforms.StringField(validators=[length(min=6, max=20)])class RegisterForm(wtforms.Form):    username = wtforms.StringField(validators=[length(min=3, max=20)])    email = wtforms.StringField(validators=[email()])    captcha = wtforms.StringField(validators=[length(min=4, max=4)])    password = wtforms.StringField(validators=[length(min=6, max=20)])    password_confirm = wtforms.StringField(validators=[EqualTo("password")])    def validate_captcha(self, field):        captcha = field.data        email = self.email.data        captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()        if captcha_model.captcha.lower() != captcha.lower():            raise wtforms.ValidationError("定制设计邮箱验证码错误!")    def validate_email(self, field):        email = field.data        user_model = UserModel.query.filter_by(email=email).first()        if user_model:            raise wtforms.ValidationError("邮箱已经存在!")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

user.py

from flask import Blueprint, render_template, request, redirect, url_for, jsonify, session, flashfrom exts import mail, dbfrom flask_mail import Messagefrom models import EmailCaptchaModel, UserModelfrom datetime import datetimefrom .forms import RegisterForm, LoginFormfrom werkzeug.security import generate_password_hash, check_password_hashimport randomimport stringbp = Blueprint("user", __name__)@bp.route("/")def index():    return render_template("index.html")@bp.route("/login", methods=['GET', 'POST'])def login():    if request.method == 'GET':        return render_template("login.html")    else:        form = LoginForm(request.form)        if form.validate():            email = form.email.data            password = form.password.data            user = UserModel.query.filter_by(email=email).first()            if user and check_password_hash(user.password, password):                session['user_id'] = user.id                return redirect("/")            else:                flash("邮箱和密码不匹配!!!")                return redirect(url_for("user.login"))        else:            flash("邮箱或密码错误!!!")            return redirect(url_for("user.login"))@bp.route("/register", methods=['GET', 'POST'])def register():    if request.method == 'GET':        return render_template("register.html")    else:        form = RegisterForm(request.form)        if form.validate():            email = form.email.data            username = form.username.data            password = form.password.data            # md5            hash_password = generate_password_hash(password)            user = UserModel(email=email, username=username, password=hash_password)            db.session.add(user)            db.session.commit()            return redirect(url_for("user.login"))        else:            return redirect(url_for("user.register"))@bp.route("/logout")def logout():    session.clear()    return redirect(url_for('user.login'))@bp.route("/captcha", methods=['POST'])def get_captcha():    # GET,POST    email = request.form.get("email")    letters = string.ascii_letters + string.digits    captcha = "".join(random.sample(letters, 4))    if email:        message = Message(            subject='【验证码】',            recipients=[email],            body=f"【验证码】您的注册验证码是{captcha},请不要告诉任何人哦!"        )        mail.send(message)        captcha_model = EmailCaptchaModel.query.filter_by(email=email).first()        if captcha_model:            captcha_model.captcha = captcha            captcha_model.create_time = datetime.now()            db.session.commit()        else:            captcha_model = EmailCaptchaModel(email=email, captcha=captcha)            db.session.add(captcha_model)            db.session.commit()        print("captcha:", captcha)        return jsonify({"code": 200})    else:        return jsonify({"code": 400, "message": "请先传递邮箱!"})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

static

bootstrap@4.6.min.css

jquery.3.6.min.js

register.js

function bindCaptchaBtnClick(){    $("#captcha-btn").on("click",function (event){        var $this = $(this);        var email = $("input[name='email']").val()        if(!email){            alert("请先输入邮箱");            return;        }        $.ajax({            url: "/user/captcha",            method: "POST",            data: {                "email": email            },            success: function (res){                var code = res['code'];                if (code == 200){                    $this.off("click")                    var countDown = 60;                    var timer = setInterval(function (){                        countDown -= 1;                        if (countDown > 0){                            $this.text(countDown+"秒后重新发送");                        }else {                            $this.text("获取验证码");                            bindCaptchaBtnClick();                            clearInterval(timer);                        }                    },1000)                    alert("验证码发送成功!");                }else{                    alert(res['message']);                }            }        })    });}$(function (){    bindCaptchaBtnClick();});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

templates

base.html

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>{% block title %}{% endblock %}</title>    <link rel="stylesheet" href="{{ url_for('static',filename='bootstrap/bootstrap@4.6.min.css') }}">    <link rel="stylesheet" href="{{ url_for('static',filename='css/css.css') }}">    {% block head %}{% endblock %}</head><body><nav class="navbar navbar-expand-lg navbar-light bg-light">    <div class="container">        <a class="navbar-brand" href="/">            <svg t="1659145665644" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6166" width="50" height="50"><path d="M512 512m-405.333333 0a405.333333 405.333333 0 1 0 810.666666 0 405.333333 405.333333 0 1 0-810.666666 0Z" fill="#4CAF50" p-id="6167"></path><path d="M640 426.666667c47.061333 0 85.333333 38.272 85.333333 85.333333s-38.272 85.333333-85.333333 85.333333-85.333333-38.272-85.333333-85.333333 38.272-85.333333 85.333333-85.333333m0-85.333334a170.666667 170.666667 0 1 0 0 341.333334 170.666667 170.666667 0 0 0 0-341.333334z" fill="#FFFFFF" p-id="6168"></path><path d="M384 426.666667c47.061333 0 85.333333 38.272 85.333333 85.333333s-38.272 85.333333-85.333333 85.333333-85.333333-38.272-85.333333-85.333333 38.272-85.333333 85.333333-85.333333m0-85.333334a170.666667 170.666667 0 1 0 0 341.333334 170.666667 170.666667 0 0 0 0-341.333334z" fill="#FFFFFF" p-id="6169"></path></svg>        </a>        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"                aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">            <span class="navbar-toggler-icon"></span>        </button>        <div class="collapse navbar-collapse" id="navbarSupportedContent">            <ul class="navbar-nav mr-auto">                <li class="nav-item active">                    <a class="nav-link" href="/">首页 <span class="sr-only">(current)</span></a>                </li>            </ul>            <ul class="navbar-nav">                {% if user %}                    <li class="nav-item">                        <span class="nav-link">{{ user.username }}</span>                    </li>                    <li class="nav-item">                        <a class="nav-link" href="{{ url_for('user.logout') }}">退出登录</a>                    </li>                {% else %}                    <li class="nav-item">                        <a class="nav-link" href="{{ url_for('user.login') }}">登录</a>                    </li>                    <li class="nav-item">                        <a class="nav-link" href="{{ url_for('user.register') }}">注册</a>                    </li>                {% endif %}            </ul>        </div>    </div></nav><div class="container">{% block body %}{% endblock %}</div></body></html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

index.html

{% extends "base.html" %}{% block title %}首页{% endblock %}{% block head %}{% endblock %}{% block body %}<h1>文章首页</h1>{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

login.html

{% extends "base.html" %}{% block title %}登录{% endblock %}{% block head %}{% endblock %}{% block body %}    <div class="row mt-4">        <div class="col"></div>        <div class="col">            <form action="{{ url_for("user.login") }}" method="post">                <div class="form-group">                    <label for="exampleInputEmail1">邮箱</label>                    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" name="email">                </div>                <div class="form-group">                    <label for="exampleInputPassword1">密码</label>                    <input type="password" name="password" class="form-control" id="exampleInputPassword1">                </div>                {% for message in get_flashed_messages() %}                    <div class="from-group">                    <div class="text-danger">{{ message }}</div>                    </div>                {% endfor %}                <div class="from-group">                    <button type="submit" class="btn btn-primary btn-block">立即登录</button>                </div>            </form>        </div>        <div class="col"></div>    </div>{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

register.html

{% extends "base.html" %}{% block title %}注册{% endblock %}{% block head %}    <script src="{{ url_for('static',filename='jquery/jquery.3.6.min.js') }}"></script>    <script src="{{ url_for('static',filename='js/register.js') }}"></script>{% endblock %}{% block body %}    <div class="row mt-4">        <div class="col"></div>        <div class="col">            <form action="{{ url_for("user.register") }}" method="post">                <div class="form-group">                    <label for="exampleInputEmail1">邮箱</label>                    <input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp"                           name="email">                    <small id="emailHelp" class="form-text text-muted">我们不会把邮箱用于其他用途</small>                </div>                <div class="form-group">                    <label for="exampleInputEmail1">验证码</label>                    <div class="input-group">                        <input type="text" class="form-control" name="captcha">                        <div class="input-group-append">                            <button class="btn btn-outline-secondary" type="button" id="captcha-btn">获取验证码</button>                        </div>                    </div>                </div>                <div class="form-group">                    <label for="exampleInputEmail1">用户名</label>                    <input type="text" class="form-control" name="username">                </div>                <div class="form-group">                    <label for="exampleInputPassword1">密码</label>                    <input type="password" class="form-control" id="exampleInputPassword1" name="password">                </div>                <div class="form-group">                    <label for="exampleInputPassword1">确认密码</label>                    <input type="password" class="form-control" name="password_confirm">                </div>                <button type="submit" class="btn btn-primary btn-block">立即注册</button>            </form>        </div>        <div class="col"></div>    </div>{% endblock %}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

app.py

from flask import Flask, session, gimport configfrom exts import db, mailfrom blueprints import user_bpfrom flask_migrate import Migratefrom models import UserModelapp = Flask(__name__)app.config.from_object(config)db.init_app(app)mail.init_app(app)migrate = Migrate(app, db)app.register_blueprint(user_bp)@app.before_requestdef before_request():    user_id = session.get("user_id")    if user_id:        try:            user = UserModel.query.get(user_id)            g.user = user        except:            g.user = None@app.context_processordef context_processor():    if hasattr(g, "user"):        return {"user": g.user}    else:        return {}if __name__ == '__main__':    app.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

config.py

# 数据库配置信息HOSTNAME = '127.0.0.1'  # 数据库地址PORT = '3306'  # 端口默认:3306DATABASE = '数据库名'USERNAME = '数据库账号'PASSWORD = '数据库密码'DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)SQLALCHEMY_DATABASE_URI = DB_URISQLALCHEMY_TRACK_MODIFICATIONS = TrueSECRET_KEY = "sdasd54as56d4a65s4"# 邮箱配置MAIL_SERVER = "smtp.qq.com"MAIL_PORT = 465MAIL_USE_TLS = FalseMAIL_USE_SSL = TrueMAIL_DEBUG = TrueMAIL_USERNAME = "发件邮箱"MAIL_PASSWORD = "授权码"MAIL_DEFAULT_SENDER = "默认发件邮箱"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

decorators.py

from flask import g, redirect, url_forfrom functools import wrapsdef login_required(func):    @wraps(func)    def wrapper(*args,**kwargs):        if hasattr(g,'user'):            return func(*args,**kwargs)        else:            return redirect(url_for("user.login"))    return wrapper
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

exts.py

from flask_sqlalchemy import SQLAlchemyfrom flask_mail import Maildb = SQLAlchemy()mail = Mail()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

models.py

from exts import dbfrom datetime import datetimeclass EmailCaptchaModel(db.Model):    __tablename__ = "email_captcha"    id = db.Column(db.Integer, primary_key=True, autoincrement=True)    email = db.Column(db.String(100), nullable=False, unique=True)    captcha = db.Column(db.String(10), nullable=False)    creat_time = db.Column(db.DateTime, default=datetime.now)class UserModel(db.Model):    __tablename__ = "user"    id = db.Column(db.Integer, primary_key=True, autoincrement=True)    username = db.Column(db.String(200), nullable=False, unique=True)    email = db.Column(db.String(100), nullable=False, unique=True)    password = db.Column(db.String(200), nullable=False)    join_time = db.Column(db.DateTime, default=datetime.now)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发