大家好,又見面了,我是你們的朋友全棧君。
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等等
發布者:全棧程序員棧長,轉載請注明出處:https://javaforall.cn/129775.html原文鏈接:https://javaforall.cn