大家好,又见面了,我是你们的朋友全栈君。
Python-Flask构建用户注册登录后端逻辑架构
1、项目结构
2、app.py
from flask import Flask,render_template
from controller.user_controller import user_controller
from datetime import timedelta
import os
app=Flask(__name__)
app.register_blueprint(user_controller)
app.config['JSON_AS_ASCII'] = False
app.config['SECRET_KEY'] = os.urandom(24) #设置为24位的字符,每次运行服务器都是不同的,所以服务器启动一次上次的session就清除。
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(minutes=30) #设置session的保存时间。
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
#在生产环境中host='0.0.0.0'
app.run(host='127.0.0.1',port=5020,debug=False)
3、user_controller
from flask import Flask,Blueprint,request,render_template,session
from dao.userdao import UserDAO
from entity.user_entity import UserEntity
user_controller=Blueprint('user_controller',__name__)
userdao=UserDAO()
userentity=UserEntity()
@user_controller.route('/login',methods=['POST'])
def login():
info=''
userentity.telphone=request.form['telphone']
userentity.password=request.form['password']
res=userdao.GetLoginInfo(userentity)
if res==None:
info='无用户信息,请注册'
return render_template('index.html',info=info)
elif res[0]==userentity.password:
info='登录成功'
session['telphone']=userentity.telphone
return render_template('index.html',info=info)
else:
info='登录失败'
return render_template('index.html',info=info)
return render_template('index.html',info='Unknow Error!!!')
@user_controller.route('/register',methods=['POST'])
def register():
info=''
userentity.telphone=request.form['telphone']
userentity.password=request.form['password']
password_again=request.form['password_again']
res=userdao.GetSameInfo(userentity)
if res:
info='手机号已被使用,请更换手机号重试'
return render_template('index.html',info=info)
elif userentity.password!=password_again:
info='两次密码不一致'
return render_template('index.html',info=info)
else:
info='注册成功'
userdao.CreateUser(userentity)
return render_template('index.html',info=info)
return render_template('index.html',info='Unknow Error!!!')
@user_controller.route('/exit',methods=['GET'])
def exit():
info=''
res=session.get('telphone')
if res==None:
info='未登录'
return render_template('index.html',info=info)
else:
session['telphone']=None
info='账号已成功注销'
return render_template('index.html',info=info)
return render_template('index.html',info='Unknow Error!!!')
4、basedao
import pymysql # 导入数据的api包
from logger.syslogger import logger
#数据库访问封装的基类
class BaseDAO():
# 1. 这些参数做私有化,就体现了封装安全性的好处
def __init__(self, host='IP', name='root', pwd='PWD', port='3306', schema='talk_system', charset='utf8mb4'):
self.__host = host
self.__name = name
self.__pwd = pwd
self.__port = port
self.__schema = schema
self.__charset = charset
self.__conn = None
self.__cursor = None
pass
# 2. 编写建立数据库连接的公有方法(通用的)
def getConnection(self):
try:
self.__conn = pymysql.connect(self.__host, self.__name, self.__pwd, self.__schema, charset=self.__charset)
except (pymysql.MySQLError, pymysql.DatabaseError, Exception):
logger.error("数据库连接异常:" + self.__host)
pass
self.__cursor = self.__conn.cursor()
pass
# 3. 封装一个通用的对数据库进行操作的方法
def execute(self, sql, params=None, isBatch=False):
try:
# self.getConnection() # 每次连接的是独立的一个连接
if self.__conn and self.__cursor:
if params:
# print('not None')
# print(parms)
if isBatch:
return self.__cursor.executemany(sql, params)
pass
else:
return self.__cursor.execute(sql, params)
else:
return self.__cursor.execute(sql)
pass
except:
logger.error("执行SQL:" + sql + " params:" + str(params) )
self.__cursor.close()
self.__conn.close()
pass
pass
# 调用存储过程
def executeProc(self, sql, params=None):
try:
if self.__conn and self.__cursor:
if params:
return self.__cursor.callproc(sql, params)
else:
return self.__cursor.callproc(sql)
pass
except:
logger.error("执行SQL:" + sql + " params:" + str(params))
self.__cursor.close()
self.__conn.close()
pass
pass
# 4. 为了支持事务管理,把对数据库的关闭的动作提取出来,封装成独立的方法
def close(self):
if self.__cursor and self.__conn:
self.__cursor.close()
self.__conn.close()
pass
# 5. 为了支持事务管理,把对数据库事务提交的动作提取出来,封装成独立的方法
def commit(self):
# print("----------")
self.__conn.commit()
pass
# 6. 如果出现异常情况,事务要回滚
def rollback(self):
self.__conn.rollback()
pass
# 查询操作
def fetchall(self, sql, params=None):
self.execute(sql, params)
return self.__cursor.fetchall()
pass
# 查询操作
def fetchone(self, sql, params=None):
self.execute(sql, params)
return self.__cursor.fetchone()
pass
# 执行存储过程
def fetchproc(self, sql, params=None):
self.executeProc(sql, params)
return self.__cursor.fetchall()
pass
pass
5、userdao
from dao.basedao import BaseDAO
from logger.syslogger import logger
import math
class UserDAO(BaseDAO):
#注册查重验证
def GetSameInfo(self,user):
sqlSelect = "select id from user where telphone=%s;"
params = (user.telphone,)
try:
super().getConnection()
result = super().fetchone(sqlSelect,params)
super().commit()
return result
except Exception as e:
logger.error("执行SQL:" + str(sqlSelect) + " 出现异常,params:" + str(e))
finally:
super().close()
# 新用户注册
def CreateUser(self, user):
try:
super().getConnection()
sqlCreate = "insert into user (id,telphone,password) values (NULL ,%s, %s);"
params = (user.telphone,user.password)
result = super().execute(sqlCreate, params)
super().commit()
return result
except Exception as e:
super().rollback()
logger.error("执行SQL:" + sqlCreate + " 出现异常,params:" + params + str(e))
finally:
super().close()
#登录验证
def GetLoginInfo(self,user):
sqlSelect = "select password from user where telphone=%s;"
params = (user.telphone,)
try:
super().getConnection()
result = super().fetchone(sqlSelect, params)
super().commit()
return result
except Exception as e:
logger.error("执行SQL:" + str(sqlSelect) + " 出现异常,params:" + str(e))
finally:
super().close()
6、user_entity
class UserEntity():
def __init__(self):
self.__id=None
self.__telphone=None
self.__password=None
@property
def id(self):
return self.__id
@id.setter
def id(self, id):
self.__id = id
@property
def telphone(self):
return self.__telphone
@telphone.setter
def telphone(self, telphone):
self.__telphone = telphone
@property
def password(self):
return self.__password
@password.setter
def password(self, password):
self.__password = password
7、syslogger
#-*- coding:utf-8 -*-
''' demo03-logging-file.py ------------------------ 日志写入文件 @Copyright: Chinasoft International·ETC '''
# 导入模块
import logging
import os
import time
# 首先,创建并设置日志logger对象
# 创建logger对象并设置信息源对象名称
logger = logging.getLogger('mainlogger')
# 设置日志的输出的输出级别
logger.setLevel(logging.DEBUG)
# 设置日志的输出格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 其次,创建并设置文件处理器FileHandler对象
dirPath = os.path.join(os.getcwd(), 'log')
if not os.path.exists(dirPath):
os.mkdir(dirPath)
logFileName = time.strftime('%Y%m%d', time.localtime())+'.log'
logPath = dirPath + os.sep + logFileName
# 创建FileHandler对象
fileHandler = logging.FileHandler(logPath)
# 设置Filehandler对象的写入信息级别
fileHandler.setLevel(logging.DEBUG)
# 设置FileHandler对象的信息格式
fileHandler.setFormatter(formatter)
# 创建一个 StreamHandler对象
consoleHandler = logging.StreamHandler()
# 设置控制台输出的信息级别
consoleHandler.setLevel(logging.DEBUG)
# 设置consoleHandler对象的信息格式
consoleHandler.setFormatter(formatter)
# 最后,logger对象添加Handler对象替换原有默认的Handler对象
logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)
# 测试输出不同级别的日志信息
''' logger.fatal('系统崩溃或发生致命性错误,导致程序中断时需要输出的信息') logger.critical('系统资源浩劫时需要输出的信息(一般很少用到)') logger.error('系统报错异常时需要输出的信息') logger.warning("系统运行警告时需要输出的信息") logger.info("一般信息数据") logger.debug("测试调试时需要输出的信息数据") '''
8、index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
{
{
info}}
<h2>登录</h2>
<form action="/login" method="post">
<label for="username">手机号:</label>
<input type="text" name="telphone" required>
<label for="password">密码:</label>
<input type="text" name="password" required>
<button type="reset">重置</button>
<button type="submit">提交</button>
</form>
<h2>注册</h2>
<form action="/register" method="post">
<label for="telphone">手机号:</label>
<input type="text" name="telphone" required>
<label for="password">密码:</label>
<input type="text" name="password" required>
<label for="password_again">密码二次确认:</label>
<input type="text" name="password_again" required>
<button type="reset">重置</button>
<button type="submit">提交</button>
</form>
<a href="/exit">账号注销</a>
</body>
</html>
9、程序启动效果图
——————————————————————————————————————————————
——————————————————————————————————————————————
——————————————————————————————————————————————
——————————————————————————————————————————————
——————————————————————————————————————————————
——————————————————————————————————————————————
——————————————————————————————————————————————
10、备注
这个架构只考虑最简单的登录、注册、注销逻辑,之后优化可以注重前端输入限制、placeholder、登录密码加盐Hash等等
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/129775.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...