效果展示:
登录
注册
主页面
项目结构
项目结构如下:
项目采用蓝图进行视图函数的管理,每个功能被放在一个小的app中。登录和注册功能放在了app_login文件夹中。
后端Python代码
app/login中的__init__.py创建了一个蓝图,内容如下:
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/8 23:19
"""登录视图的蓝图"""
from flask import Blueprint
login = Blueprint("login", __name__)
from . import view
models.py创建了一个数据模型User,对应数据库中的用户表,内容如下:
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/4 20:00
"""登录需要的数据库模型(用户表)"""
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin
from app import db
class User(UserMixin, db.Model):
# 第一个参数指定字段类型,后面设置属性
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
count = db.Column(db.String(128), nullable=False)
password = db.Column(db.String(128), nullable=False)
def __init__(self, count, password):
self.count = count
self.password = password
def set_password(self, password):
self.password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password, password)
if __name__ == '__main__':
user = User(count='0101', password=2021)
db.session.add(user)
db.session.commit()
viesw.py存放登录、注册的视图函数,内容如下:
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/6 11:39
"""登录的视图函数"""
from flask import request, render_template, redirect, url_for, flash
from flask_login import login_required, login_user
from . import login
from .models import User
from app import login_manager
@login_manager.user_loader
def load_user(user_id): # 创建用户加载回调函数,接受用户 ID 作为参数
user = User.query.get(int(user_id)) # 用 ID 作为 User 模型的主键查询对应的用户
return user # 返回用户对象
@login.route('/index', methods=['GET', 'POST'])
@login_required
def index():
if request.method == "GET":
return render_template('index.html')
@login.route('/register', methods=['GET', 'POST'])
def register():
# 如果请求为post
if request.method == 'POST':
count = request.form.get('count')
password = request.form.get('password')
repassword = request.form.get('repassword')
print(count, password)
from app import db
if password == repassword:
user = User(count, password)
user.set_password(password)
db.session.add(user)
db.session.commit()
return '注册成功'
else:
return '两次密码不一致'
# 请求为get
return render_template('register.html')
@login.route('/', methods=['GET', 'POST'])
@login.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
count = request.form['count']
password = request.form['password']
print(password)
if not count or not password:
flash('Invalid input.')
return redirect(url_for('login'))
user = User.query.filter_by(count=count).first()
if not user:
flash("用户不存在")
return redirect(url_for('login.login'))
if count == user.count and user.check_password(password):
login_user(user) # 登入用户
flash('Login success.')
print("登录成功")
return redirect(url_for('login.index')) # 重定向到主页
flash('Invalid username or password.') # 如果验证失败,显示错误消息
return redirect(url_for('templates.login')) # 重定向回登录页面
return render_template('login.html')
配置文件config.py
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/3 15:08
"""各种配置类"""
class BaseConfig(object):
"""所有配置类的基类"""
SECRET_KEY = "LOVE"
DEBUG = True
TESTING = False
VISIT_TIME = 0 # 网站访问次数
# 数据库配置
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:自己的MySql密码@localhost/personalwebsite"
SQLALCHEMY_TRACK_MODIFICATIONS = False # 是否追踪数据库的修改
class ProductionConfig(BaseConfig):
"""生产环境下的配置类"""
DEBUG = False
class DevelopmentConfig(BaseConfig):
"""开发模式下的配置类"""
DEBUG = True
TESTING = True
app/__init__.py
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/3 1:54
"""构建app,注册蓝图"""
from flask import Flask
from config import BaseConfig
from flask_login import LoginManager
from flask_sqlalchemy import SQLAlchemy
login_manager = LoginManager()
login_manager.session_protection = 'strong'
login_manager.login_view = 'login'
db = SQLAlchemy()
def register_bp(app):
"""
注册蓝图
:param app:
:return:
"""
from .app_login import login as login_blueprint
app.register_blueprint(login_blueprint)
def database(app, db):
"""
初始化数据库
:param app:
:return:
"""
db.init_app(app)
db.create_all()
db.session.commit()
def create_app():
my_app = Flask(__name__)
with my_app.app_context():
# app注册蓝图
register_bp(my_app)
# app加载配置
my_app.config.from_object(BaseConfig)
# 数据库管理对象
database(my_app, db)
# 用于登录验证
login_manager.init_app(my_app)
login_manager.login_view = 'login.login'
return my_app
启动文件manager.py
# coding: utf-8
# 作者(@Author): Messimeimei
# 创建时间(@Created_time): 2023/1/3 13:50
"""启动文件"""
from app import create_app
from flask import render_template, session
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
前端代码(没有使用bootstrap)
html部分
登录login.html页面
登录页面
入口
注册register.html页面
Title
注册
主页面index.html
登录页面
css部分
login.css
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-size: cover;
background: url(../images/bg.jpg) no-repeat fixed center 0;
-webkit-background-size: cover;
-o-background-size: cover;
-moz-background-size: cover;
-ms-background-size: cover;
}
.login-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 400px;
padding: 40px;
background: rgba(16, 17, 19, 0.58);
box-sizing: border-box;
box-shadow: 0 10px 25px rgb(16, 17, 19);
border-radius: 10px;
}
.login-box h2 {
margin: 0 0 30px;
padding: 0;
text-align: center;
color: #ffffff;
}
.login-box .login-field {
position: relative;
}
.login-box .login-field input {
width: 100%;
padding: 10px 0;
font-size: 16px;
color: #ffffff;
margin-bottom: 30px;
border: none;
border-bottom: 1px solid #ffffff;
outline: none;
background: transparent;
}
.login-box .login-field label {
position: absolute;
top: 0;
left: 0;
letter-spacing: 1px;
padding: 10px 0;
font-size: 16px;
color: #ffffff;
pointer-events: none;
transition: .5s;
}
.login-box .login-field input:focus ~ label,
.login-box .login-field input:valid ~ label {
top: -23px;
left: 0;
color: aqua;
font-size: 12px;
}
.login-box button {
border: none;
outline: none;
color: #fff;
background: #03a9f4;
padding: 10px 20px;
cursor: pointer;
border-radius: 5px;
}
#myloginlabel{
position: relative;
background-color: rgb(3, 168, 243);
border: 1px solid rgb(190, 225, 255);
width: 100px;
height: 30px;
font-size: 12px;
color: rgb(255, 255, 255);
font-weight: 200;
margin-top: 10px;
text-align: center;
border-radius: 20px;
padding: 10px;
}
index.css
body {
margin: 0;
padding: 0;
font-family: sans-serif;
background-size: cover;
background: url(../images/index.jpg) no-repeat fixed center 0;
-webkit-background-size: cover;
-o-background-size: cover;
-moz-background-size: cover;
-ms-background-size: cover;
}
js部分
register.js
function topggleForm() {
var container = document.querySelector('.container');
container.classList.toggle('active');
}
两张背景图片(有需求自取,当然也可以换自己喜欢的,推荐一个网站https://pixabay.com/zh/)