第十四章 购物车系统登录注册注销
购物车系统登录注册注销
1.项目需求
业务逻辑功能
"1":登录
"2":注册
"3":查看余额
"4":转账
"5":存款
"6":取款
"7":查看流水
"8":购物
"9":查看购买商品
"10":注销
这节课我们先讲注册,登录,注销
2.一个完整的项目
我们上节课讲了模块
介绍了模块的优势:
1.程序的组织结构更加清晰
2.维护起来更加方便
3.模块可以被重复使用
4.提高了程序员的开发效率
这节课老师就通过这个购物车系统来证明这些优势
需要有的模块目录
运行启动目录文件
bin
start.py
配置文件
conf
setting.py
执行任务文件
core
src.py
数据存储目录
db
db_handle.py
业务逻辑接口
interface
bank.py
shop.py
user.py
公用逻辑接口
lib
common.py
历史日志记录
log
user1.log
那么我们来创建一下项目
1.第一种以shoppingcart为根目录
第一种导入模块不会报红色波浪线
2.第二种不以shoppingcart为根目录创建
第二种导入模块会报红色波浪线,对程序没影响但是会影响效率
第二种报红色波浪线的解决办法
将文件夹Mark Directory as成source root的方法
pycharm标记成项目路径来源文件夹
文件夹变成蓝色
3.代码编写流程
一.启动程序路径配置bin/start.py
1.拿到当前的项目执行目录
import sys
import os
# 拿到当前的执行路径
print(os.path.dirname(__file__))
Source_path = os.path.dirname(os.path.dirname(__file__))
print(Source_path)
2.添加到解释器的路径里面去
sys.path.append(Source_path)
# 添加到解释器路径当中
print(sys.path)
3.启动core/src.py文件run函数
from core import src
if __name__ == '__main__':
src.run()
补充 __ name __
print(__name__)
# # start.py作为执行文件,当前文件作为主程序
运行其他文件比如spam.py
import start
我们看到运行自己print(__ name __ ) 结果是 __ main __ ,而把导入start.py 这个结果确实 start
所有我们就可以通过一个if判断的条件,来判断你的这个文件是不是主程序。
if __ name __ == '__ main __':
if __name__ == '__main__':# 的意思是:只有在本程序直接运行的情况下,才会执行某些操作。
src.run()
4.写run函数,通过序号选择相应的函数功能
def login():
'''
登录函数,密码输错三次锁定,用户名输错可以一直输入
:return:
'''
def register():
print('注册')
def check_balance():
print('查看余额')
def transfer():
print('转账')
def repay():
print('还款')
def withdraw():
print('取款')
def check_record():
print('查看流水')
def shopping():
print('购物')
def look_shoppingcart():
print('查看购物车')
fun_dic={'1':login,
'2':register,
'3':check_balance,
'4':transfer,
'5':repay,
'6':withdraw,
'7':check_record,
'8':shopping,
'9':look_shoppingcart,
'10':loginout,
}
def run():
while True:
print("""
"1":登录
"2":注册
"3":查看余额
"4":转账
"5":还款
"6":取款
"7":查看流水
"8":购物
"9":查看购买商品
"10":注销
""")
choice=input('输入操作编号').strip()
if choice not in fun_dic:continue
# fun_dic[choice]拿到函数内存地址,加括号调用
fun_dic[choice]()
二.设置一个用户的信息,登录的状态
user_data={'name':None,
'is_auth':False,}
三.注册register之1接口user.get_userinfo_by_name
def register():
if user_data['is_auth']:
print('你已登录')
return
print('注册')
while True:
name = input('输入用户名').strip()
# 四
# 查看用户是否已经注册需要用到接口interface 对应的 user
user_dic = user.get_userinfo_by_name(name)
#
print(user_dic)
五.写一个查询用户信息的接口
def get_userinfo_by_name(name):
'''
写一个查询用户信息的接口
:param name:
:return:
'''
# 这里需要用到一个db 下面的 db_handle 数据管理的方法在这个文件夹下
# 这里需要返回用户信息 ???
return db_serialization.select(name)
六.查看用户信息接口,通过反序列化去查询
思路保存到db/db_handle.py
# 思路
# 1.路径在 conf/setting.py进行配置
# 2.有json模块,存储成序列化文件
假设已经注册了,我们读取序列化文件,也就是反序列化李老师.json
db_handle.py之1
import os
import json
from conf import setting
class Serialization:
def select(self,name):
# 读取一个文件信息,我们需要什么?
# 1.需要文件路径
# 思路
# 我们可以通过json文件名进行查询,
# 如果查到文件存在,说明已经注册了,
# 不存在,代表没注册
#七 路径写道setting里面 ???
path = r'%s/%s.json'%(setting.DB_path,name)
# 有李老师这个json文件就返回,没有就返回False
# 返回给谁 bank shop user 这个三个接口 都可能用的上
if os.path.isfile(path):
with open(path,'r',encoding='utf-8')as f:
# 对序列化json文件操作load
return json.load(f)
else:
return False
# 记得要实例化
db_serialization=Serialization()
七.setting.py
# @Author : 大海
# @File : setting.py
import os
# 拿到当前的执行路径
Source_path = os.path.dirname(os.path.dirname(__file__))
DB_path = os.path.join(Source_path,'db')
# 添加日志文件路径
LOG1_path=os.path.join(Source_path,'log','user1.log')
八.注册register之1接口user.register_user
def register():
if user_data['is_auth']:
print('你已登录')
return
print('注册')
while True:
name = input('输入用户名').strip()
# 四
# 查看用户是否已经注册需要用到接口interface 对应的 user
user_dic = user.get_userinfo_by_name(name)
#
print(user_dic)
if not user_dic:
pwd = input('输入密码').strip()
pwd1 = input('确认密码').strip()
if pwd == pwd1:
# 八
user.register_user(name,pwd)
break
else:
print('2次密码不一致')
else:
print('用户名已经存在')
九.注册拼接的字典进行序列化注册
register_user接口1
def register_user(name,password,balance=15000):
'''
注册用户接口
:param name:
:param password:
:param balance:
:return:
'''
# 信息传入定义的字典
user_dic = {'name': name, 'password': password, 'locked': False, 'account': balance, 'shopping_cart': {}, 'bankflow': []}
# 这个字典到时候会存储成json文件
# 需要通过谁写入 ???
# db包 db_handle模块 的 db_serialization 对象的方法
# db_serialization
db_serialization.update(user_dic)
db_handle.py之2
import os
import json
from conf import setting
class Serialization:
def select(self,name):
# 读取一个文件信息,我们需要什么?
# 1.需要文件路径
# 思路
# 我们可以通过json文件名进行查询,
# 如果查到文件存在,说明已经注册了,
# 不存在,代表没注册
# 路径写道setting里面 ???
path = r'%s/%s.json'%(setting.DB_path,name)
# 有ljy这个json文件就返回,没有就返回False
# 返回给谁 bank shop user 这个三个接口 都可能用的上
if os.path.isfile(path):
with open(path,'r',encoding='utf-8')as f:
# 对序列化json文件操作load
return json.load(f)
else:
return False
# 十.序列化存储用户信息
def update(self,user_dic):
# 拿到 # 路径
path_file = os.path.join(setting.Source_path,'db','%s.json'%user_dic['name'])
# 注册是利用json文件名注册
with open(path_file, 'w', encoding='utf-8') as f:
# 对序列化json文件操dump
json.dump(user_dic, f)
# 刷新
f.flush()
# 记得要实例化
db_serialization=Serialization()
register_user接口2之添加日志
def register_user(name,password,balance=15000):
'''
注册用户接口
:param name:
:param password:
:param balance:
:return:
'''
# 信息传入定义的字典
user_dic = {'name': name, 'password': password, 'locked': False, 'account': balance, 'shopping_cart': {}, 'bankflow': []}
# 这个字典到时候会存储成json文件
# 需要通过谁写入 ???
# db包 db_handle模块 的 db_serialization 对象的方法
# db_serialization
db_serialization.update(user_dic)
print('%s 注册了' % name)
# 十一 调用日志的接口 common存储
# 存储一个日志
# 日志是公用的 在lib 文件夹 common 写方法 数据存储到 log 文件夹里面
# 需要添加log 下面日志文件的路径到 setting 里面
common.log('%s 注册了' % name)
十二.日志写入数据方法
def log(msg):
# 当前时间年月日时分秒
current_time = time.strftime('%Y-%m-%d %X')
with open(setting.LOG1_path, 'a', encoding='utf-8') as f:
f.write(current_time + '-' * 5 + msg + '\n')
十三.login
import time
def login():
'''
登录函数,密码输错三次锁定,用户名输错可以一直输入
:return:
'''
if user_data['is_auth']:
print('你已登录')
return
print('请登录')
count = 0
while True:
name = input('输入用户名').strip()
# 九
# 需要查询是否用户存在
# 省了多少代码
user_dic = user.get_userinfo_by_name(name)
if user_dic:
# 是否锁定
print(user_dic['locked'])
# 先写锁定
if user_dic['locked']:
# 十四 解锁接口
# 需要的解锁定 写入 user_dic locked 变 True 写入 json数据修改
time.sleep(5)
user.unlock_user(name)
count = 0
continue
pwd = input('输入密码').strip()
if user_dic['password'] == pwd and not user_dic == user_dic['locked']:
user_data['name'] = name
user_data['is_auth'] = True
print('登录成功')
break
else:
print('密码错误')
count += 1
if count >= 3:
# 十三。锁定接口
# 需要的是锁定 写入 user_dic locked 变 True 写入 json数据修改
user.lock_user(name)
else:
print('用户名不存在')
十四.锁定和解锁接口
def unlock_user(name):
'''
解锁用户接口
:param name:
:return:
'''
# 拿到用户的信息
user_dic = get_userinfo_by_name(name)
user_dic['locked'] = False
db_serialization.update(user_dic)
print('已经解锁')
common.log('已经解锁')
def lock_user(name):
'''
解锁用户接口
:param name:
:return:
'''
# 拿到用户的信息
user_dic = get_userinfo_by_name(name)
user_dic['locked'] = True
db_serialization.update(user_dic)
print('已被锁定')
# 记录日志
common.log('已被锁定').锁定和解锁接口
4.项目文件
start.py
import sys
import os
Source_path = os.path.dirname(os.path.dirname(__file__))
# D:/shopping_cartA8
# print(Source_path)
sys.path.append(Source_path)
# print(sys.path)
from core import src
#
#
# src.run()
# print(__name__)
# # start.py作为执行文件,当前文件作为主程序
# if __name__ == '__main__':的意思是:只有在本程序直接运行的情况下,才会执行某些操作。
if __name__ == '__main__':
src.run()
setting.py
# @Author : 大海
# @File : setting.py
import os
Source_path = os.path.dirname(os.path.dirname(__file__))
# D:/shopping_cartA8
# D:/shopping_cartA8/db
# D:/shopping_cartA8\db
# 添加保存用户数据路径
DB_path = os.path.join(Source_path,'db')
# print(DB_path)
# 添加保存日志信息路径
LOG1_path=os.path.join(Source_path,'log','user1.log')
# D:/shopping_cartA8\log\user1.log
# print(LOG1_path)
src.py
from interface import user
# 设置一个用户的信息,登录的状态
user_data={'name':None,
'is_auth':False,}
from lib import common
import time
def login():
'''
登录函数,密码输错三次锁定,用户名输错可以一直输入
:return:
'''
if user_data['is_auth']:
print('已登录')
return
print('请登录')
count = 0
while True:
name = input('输入用户名').strip()
# 需要查询是否用户存在
# 开始省代码
user_dic = user.get_userinfo_by_name(name)
if user_dic:
# 是否锁定
# 锁定状态
if user_dic['locked']:
time.sleep(5)
count = 0
# 需要的解锁定 写入 user_dic locked 变 False 写入 json数据修改
# ???
user.unlock_user(name)
continue
pwd = input('输入密码').strip()
if user_dic['password'] == pwd and user_dic['locked'] == False:
user_data['name'] = name
user_data['is_auth'] = True
common.log('登录成功')
print('登录成功')
break
else:
print('密码错误')
count += 1
if count>=3:
user.lock_user(name)
else:
print('用户名不存在')
# 注册函数
def register():
if user_data['is_auth']:
print('已登录')
return
print('注册')
while True:
name = input('输入用户名').strip()
# 查看用户是否已经注册需要用到接口interface 对应的 user
user_dic=user.get_userinfo_by_name(name)
# print(user_dic)
if not user_dic:
pwd = input('输入密码').strip()
pwd1 = input('确认密码').strip()
if pwd == pwd1:
user.register_user(name,pwd)
break
else:
print('用户名已经存在')
def check_balance():
print('查看余额')
def transfer():
print('转账')
def repay():
print('存款')
def withdraw():
print('取款')
def check_record():
print('查看流水')
def shopping():
print('购物')
def look_shoppingcart():
print('查看购物车')
def loginout():
user_data['is_auth'] = False
print('注销')
fun_dic={'1':login,
'2':register,
'3':check_balance,
'4':transfer,
'5':repay,
'6':withdraw,
'7':check_record,
'8':shopping,
'9':look_shoppingcart,
'10':loginout,
}
# 选择运行函数
def run():
while True:
print("""
"1":登录
"2":注册
"3":查看余额
"4":转账
"5":还款
"6":取款
"7":查看流水
"8":购物
"9":查看购买商品
"10":注销
""")
choice = input('输入操作编号').strip()
if choice not in fun_dic:continue
# print(fun_dic[choice])
fun_dic[choice]()
db_handle.py
# 六.注册的用户信息保存成序列化json文件
# 思路
# 1.路径
# 2.有json模块,存储成序列化文件
import json
import os
from conf import setting
class Serialization:
# 反序列化方法,读的方法
def select(self,name):
# print(name)
# print('select')
# 读取一个文件信息,我们需要什么?
# 1.需要文件路径
# 思路
# 我们可以通过json文件名进行查询,
# 如果查到文件存在,说明已经注册了,
# 不存在,代表没注册
# 路径写道setting里面 ???
# D:\shopping_cartA8\db/dahai.json
# 存在
# D:/shoping_cart_A7\db/李老师.json
path = r'%s/%s.json'%(setting.DB_path,name)
# print(path)
# 有李老师.json这个json文件就返回,没有就返回False
# 返回给谁 bank shop user 这个三个接口 都可能用的上
if os.path.isfile(path):
# print('文件存在')
# print('用户存在')
with open(path,'r',encoding='utf-8')as f:
dic=json.load(f)
# print(dic)
return dic
else:
# print('文件不存在')
# print('用户不存在')
return False
# 序列化
def update(self,user_dic):
path_file = os.path.join(setting.DB_path,'%s.json'%user_dic['name'])
# D:\shopping_cartA8\db\李老师.json
# 注册是利用json文件名注册 数据写入文件
with open(path_file,'w',encoding='utf-8')as f:
json.dump(user_dic,f)
f.flush()
db_serialization=Serialization()
user.py
from db.db_handle import db_serialization
from lib import common
def get_userinfo_by_name(name):
'''
写一个查询用户信息的接口
:param name:
:return:
'''
# 这里需要用到一个db 下面的 db_handle 数据管理的方法在这个文件夹下
# 这里需要返回用户信息 ???
return db_serialization.select(name)
# return ????
def register_user(name,password,balance= 15000):
'''
注册用户接口
:param name:
:param password:
:param balance:
:return:
'''
# 信息传入定义的字典
user_dic = {'name': name, 'password': password, 'locked': False, 'account': balance, 'shopping_cart': {},
'bankflow': []}
# 这个字典到时候会存储成json文件
# 需要通过谁写入 ???
# db包 db_handle模块 的 db_serialization 对象的方法
# db_serialization
db_serialization.update(user_dic)
print('%s 注册了'%name)
# 存储一个日志
# 日志是公用的 在lib 文件夹 common 写方法 数据存储到 log 文件夹里面
# 需要添加log 下面日志文件的路径到 setting 里面
common.log('%s 注册了'%name)
def lock_user(name):
'''
锁定用户接口
:param name:
:return:
'''
# 拿到注册用户的字典信息
user_dic = db_serialization.select(name)
# 锁定改成True
user_dic['locked'] = True
# 重新写入字典信息
db_serialization.update(user_dic)
print('密码输入错误3次锁定5秒,请5秒后再登录')
print('已被锁定')
# 记录日志
common.log('已被锁定')
def unlock_user(name):
'''
解锁用户接口
:param name:
:return:
'''
# 拿到注册用户的字典信息
user_dic = db_serialization.select(name)
# 锁定改成True
user_dic['locked'] = False
# 重新写入字典信息
db_serialization.update(user_dic)
print('已被解锁')
# 记录日志
common.log('已被解锁')
common.py
from conf import setting
import time
# 日志写入数据方法
def log(msg):
current_time = time.strftime('%Y-%m-%d %X')
with open(setting.LOG1_path,'a',encoding='utf-8')as f:
f.write(current_time+'-'*6+msg+'\n')