ATM购物车项目总结
项目实现思路
ATM项目
ATM架构设计
三层架构
core目录下的src.py(浏览器) (展示层)
interface目录下的多个py文件(框架) (核心逻辑层)
db目录下db_handler.py(数据库服务) (数据处理层)
优先实现功能
在src.py的展示层写面条版的函数,先实现主题功能,暂时别想着优化
拆分函数
如下图是一个用户注册功能函数:
我们要做的是将其到interface、db构成三层架构
拆分到哪?
核心逻辑层 有user bank shop admin等文件,负责不同的功能, 将跟user相关的代码(登录、注册) 放入相应的user_innerface.py文件
然后如果在innerface层下需要进行数据操作,就调用db层的函数。
请注意:展示层只能访问逻辑层,不能访问数据层。
项目路径展示
项目启动文件 start.py
项目启动文件start.py可以放在项目根路径,也可以放在bin文件夹下。
该文件首先要做的第一件事就是使用os.path.dirname获取将当前项目路径,并将其导入sys.path。
然后就是调用展示层文件src.py。
使用if name == __name__:
标志这个文件是启动文件。
请无视飘红,这是pycharm的小bug,实际程序是可以运行的。
配置文件 setting.py
配置文件应该存放的是一些不会变动的信息,如项目的根路径、数据库的路径、日志的存放位置。
当其他模块要用这些路径的时候的时候,从配置文件导入即可。注意当数据库db不存在时,settings.py会进行创建,所以在第三层一定要导入settings.py。
日志配置字典
可以先别急着实现日志功能,中后期再添加日志。
关于日志模块的配置信息,应该写在settings.py文件内,并且封装成函数方便调用:
日志函数
日志函数属于公共功能,应该放在common.py。
在每个接口文件的开头都放一个logger,方便调用,下面拿bank接口文件举例:
所有这个文件内产生的日志,都是银行日志。
展示层 src.py
用户注册
获取用户输入
获取用户输入包括 获取用户名和获取密码
可自行添加:退出、输入两次密码比对
这两个功能逻辑简单,可以放在展示层
md5加密
使用hashlib对用户输入的密码进行md5加密,将密文保存到数据层,下次用户登录直接比对密文。
展示层只调用加密函数,加密函数应该存放于lib/common.py路径下:
调user功能接口
将用户名、密文输入user接口函数:
接口函数在核心逻辑层,在user_interface.py文件内:
逻辑层调用数据层的select函数,检查用户是否注册。再建立用户信息字典,最后调用数据层的save函数,输入用户信息字典,保存数据。
用户登录
基本流程
1.获取用户输入
2.md5加密
3.调user功能接口
调user功能接口:
接口返回值一致性
这个接口返回两个值:登录状态,信息
请注意之前注册接口的返回值只有一个值,这样我们每次调接口都要查看到底有几个返回值,容易混淆。为了保持接口返回值一致性,应该都改成返回两个值
将用户名和密文传入login_interface函数:
这里需要注意的是,每次传入的参数,都需要进行校验,保证传入干净的数据。
登录成功修改全局字典
当登录成功后,会修改全局字典:
将全局字典'username'键的值从空改成当前用户。
全局字典对应的是cookies。也就是你登录网站之后,网站会给你返回一个通行证,浏览器帮你把这个通行证存在本地。下一次登录就拿出来给网站看,也就不需要重新输入用户名密码了。
还有一个原因就是,使用的用户多了之后,如果放在第二层、第三层则会增大服务器的开销,所以放在第一层让用户承担开销,更为合理。
登录校验装饰器
由于我们希望只有登录的用户,才能使用更多功能,所以要给其他函数添加装饰器。
只有当全局字典是有值的,才会执行被装饰函数。还记得吗,登录成功会将全局字典的值改为当前用户。
循环导入
装饰器理论上应该放入common.py,因为登录检验的逻辑不是我们应该给用户展示的,但是放入common.py容易引起循环导入:
查看余额
从全局字典获取当前用户名
调bank功能接口
这个功能比较简单,先调用bank接口(之前是user接口),再调用select函数得到用户信息字典,返回用户的余额数据即可。
余额提现
从全局字典获取当前用户名
调bank功能接口
传入用户名、提现金额两个参数。
接口函数在逻辑层:
判断用户输入是否是整数或小数
对用户输入的数字,我们要进行校验,可以将校验的代码封装成函数,放在common.py。需要用的时候直接调用。这里建议在第二层做校验用户输入,第一层只能输入数据。
手续费 免费额度
在用户提现时收取一定手续费,手续费的数据应该放在settings.py下,便于管理。
免费额度的意思是:在免费额度内,用户提现不需要手续费,如果超过额度,就需要手续费。
以支付宝为例:每个用户有2万元的免费额度,超出后按照0.1%收取手续费。
实现思路:可以在用户信息字典中添加一个键值对,存放该用户的提现免费额度。
账户充值
与余额提现很相似,故省略。
repay:
repay_interface:
用户转账
转账相对来说,比前面复杂一点点,需要指名给谁转账:
转账逻辑
关于转账需要注意:
- 不能转账给自己
- 确认被转账的人存在
- 确认用户余额足够转账
- 确认转账之后当前用户金额减少
- 确认被转账用户金额增加
查看流水
在发生充值、提现、转账、购物车结算,这种涉及到账户余额变化的事件时,要将金额变动的信息加入用户信息字典。只要有钱的变动,就应该有流水信息。
所以应该在上述函数中,都添加一些代码,将流水信息添加到用户字典。
添加时间信息 转账流水
查看流水,就是将用户信息字典的流水信息拿出来展示,这个功能实现很简单,不再赘述。
也可以给流水添加时间信息:
注意转账功能的流水,既需要给当前用户添加流水,也需要给被转账的用户添加流水。
日志也可以实现这个功能,建议后期再添加日志。
添加购物车
核心逻辑
user_data = {'shop_car': {'印度飞饼': [20, 22]}} # 现在的字典
swap_dict = {'印度飞饼': [100, 22], '仿真玩偶': [1, 10000]} # 临时字典
for good in swap_dict: # 1.键一个一个取出来
if good in user_data.get('shop_car'): # 2.如果商品在user-data中
user_data.get('shop_car').get(good)[0] += swap_dict.get(good)[0] # #3.修改数量的值
else:
user_data.get('shop_car')[good] = [swap_dict.get(good)[0], swap_dict.get(good)[1]] # 如果不存在就新增键值对
print(user_data)
展示商品
用户需要先查看商品,才能添加购物车。可以在逻辑层写一个展示商品的函数。商品数据也可以放在逻辑层。商品数据也可以保存在文件,做成配置项,从settings导入。
使用临时字典
什么叫临时字典?在添加购物车时,我们运行用户循环添加,直到用户输入q则停止添加。如果不使用临时字典,则用户每次添加,都会进行一次数据层的文件写入。使用临时字典,则是将数据保存在字典中,等到用户输入q,再将字典中的数据一次性写入文件。总得来说就是减少了写入的次数。
展示临时字典
因为临时字典是在程序运行中临时存在的,所以无法通过查看文件中的用户信息,来看到临时字典里的东西。
只能及时展示,每次循环临时字典都会变动。
查看购物车
调用shop接口查看用户字典即可,很简单,不再赘述。购物车是空的时候,要进行提示。
清空购物车
主要逻辑
从用户字典读出当前购物车信息,对商品价格进行计算,比对余额是否充足,将余额减去商品价格,最后将购物车清空,记录金额变动的流水,最后写入用户信息字典。
管理员功能
校对用户信息字典
管理员用户也是用户,只不过他有一个键值对比较特殊is_admin:true
。已经登录的用户想使用管理员功能,就要先进行用户字典中数据值的校对,如果is_admin == true
则可以使用管理员功能。说明一点,对于普通的用户注册,它们的信息字典从创建开始默认:is_admin:false
。也可以设置只有管理员用户才有这个键值对。
调用接口函数查看当前用户是不是管理员:
确认is_admin这个键的值:
校对全局变量
给全局变量字典扩充一个键值对:
登录成功后,会将这两个键值对的值都进行修改。如果是管理员登录则会将'is_admin'修改为true。
此时获取当前全局变量字典的信息,就可以进行是否为管理员的校验了。
有参装饰器
装饰器要能区分哪些是普通函数,哪些是管理员函数。所以要外界传一个参数,告诉装饰器现在装饰的是普通函数还是管理员函数。如果是管理员函数就多加一个分支,如果是普通函数就按照原来进行。
先校验用户是否登录,再校验当前功能函数级别。
如果这个函数是普通函数(装饰器传参为normal),则直接执行。
如果这个函数是管理员函数(type=='admin'),则校验全局字典的is_admin键值对。如果是True,则继续执行。
如果is_admin == false
则是普通用户,就走else不然其使用管理员函数。
给函数装上有参装饰器:
这样看起来确实更加清晰推荐使用,但是装饰器获取的还是全局变量字典的值(cookies),全局变量在展示层,理论上用户可以修改,所以我觉得应该还是有安全隐患。但是也不钻牛角尖了,就这样了!!而且使用有参装饰器和全局字典就可以少写一个校验admin的接口函数。
冻结用户
冻结用户之前,管理员先要能查看所有的用户吧,所以要在数据层写一个查看所有用户的函数。
db目录大概是这样:
这个函数返回用户名的列表:
在接口层改用户的is_lock键值对:
在登录函数添加判断是否锁定的逻辑:
查看文件的函数
可以扩展这个查看文件的函数,给他传入参数(一个目录,文件后缀名),他给你返回一个此目录下所有你指定后缀名的文件。比如指定txt,就给你返回目录下所有文本文件。
解冻用户
会冻结难道不会解冻吗?
提示:获取db目录所有被冻结的用户名单
def unlock_user():
cold_user = []
user_list = db_handler.check_file()
# 1.获取所有被冻结的用户
for user in user_list:
user_data_dict = db_handler.select(user)
cold_massage = user_data_dict.get('is_lock')
if cold_massage:
cold_user.append(user)
else:
continue
# 2.展示被冻用户
for num, user in enumerate(cold_user):
print(f'编号{num},用户名:{user}')
while True:
# 3.解冻
admin_choice = input(f'请输入要冻结的用户编号>>>')
if admin_choice.lower() == 'q':
break
if not admin_choice.isdigit():
print('输入错误')
continue
admin_choice = int(admin_choice)
if admin_choice not in list(range(len(cold_user))):
print('超出范围')
continue
user_name = cold_user[admin_choice]
user_data_dict = db_handler.select(user_name)
user_data_dict['is_lock'] = False
print(f'解冻{user_name}成功')
db_handler.save(user_data_dict)
逻辑层 interface
对传入数据进行校验
逻辑层会接受到用户传入的数据,为了安全性,我们必须对传入数据进行校验。
数据层 db_handler.py
数据层的优化
数据层总是需要用到项目路径(base_path)、数据库路径(db_path),这两个路径都是不变的。
在每个函数内都写很麻烦,我们可以将其放入配置文件conf/setting.py
优化前:
放入配置文件:
(当db不存在就创建)
在数据层(db_hander.py)导入即可form conf import setting
数据层的select函数
注意:当用户存在,返回用户信息的字典,当用户不存在,返回None。
数据层的save函数
ensure_ascii参数保证写入的时候不会把中文转成unicode编码,增强可读性。
common文件到底有什么?
- 加密
- 用户登录装饰器
- 用户输入校验
- 日志函数
ATM购物车项目总结的更多相关文章
- 阶段性项目 ATM+购物车项目
ATM + 购物车https://www.cnblogs.com/kermitjam/articles/10687180.html readme 内容前戏: 一个项目是如何从无到有的. 一 需求分析 ...
- ATM + 购物车项目
''' 存放配置文件 ''' import os #获取项目根目录 BASE_PATH=os.path.dirname(os.path.dirname(__file__)) #获取用户目录 USER_ ...
- ATM+购物车项目流程
目录 需求分析 架构设计 功能实现 搭建文件目录 conf配置文件夹 lib公共功能文件夹 db数据文件夹 interface业务逻辑层文件夹 core表现层文件夹 测试 最外层功能(src.py) ...
- ATM购物车+三层结构项目设计
ATM购物车项目 模拟实现一个ATM + 购物商城程序. 该程序实现普通用户的登录注册.提现充值还款等功能,并且支持到网上商城购物的功能. 账户余额足够支付商品价格时,扣款支付:余额不足时,无法支付, ...
- ATM购物车程序项目规范(更新到高级版)
ATM购物车程序(高级版) 之前的低级版本已经删除,现在的内容太多,没时间把内容上传,有时间我会把项目源码奉上! 我已经把整个项目源码传到群文件里了,需要的可以加主页qq群号.同时群内也有免费的学习资 ...
- python以ATM+购物车剖析一个项目的由来及流程
ATM+购物车 一个项目是如何从无到有的 ''' 项目的由来,几个阶段 0.采集项目需求 1.需求分析 2.程序的架构设计 3.分任务开发 4.测试 5.上线运行 ''' 需求分析: # 对项目需求进 ...
- 项目: ATM+购物车
ATM+购物车 项目文件: 介绍 以下为文件夹层次和内容: readme.md 1. 需求 模拟银行取款 + 购物全过程 1.注册 2.登录 3.提现 4.还款 5.转账 6.查看余额 7.查看购物车 ...
- day19 十九、ATM+购物车
项目:ATM+购物车 作业需求:模拟实现一个ATM + 购物商城程序1.额度 15000或自定义 2.实现购物商城,买东西加入 购物车,调用信用卡接口结账 3.可以提现,手续费5% 4.每月22号出账 ...
- Python 入门基础16 -- ATM + 购物车
ATM + 购物车 1.需求分析 2.设计程序以及程序的架构 设计程序的好处: - 扩展性强 - 逻辑清晰 3.分任务开发 4.测试 黑盒: 白盒: 对程序性能的测试 5.上线运行 # Tank -- ...
- Python实战之ATM+购物车
ATM + 购物车 需求分析 ''' - 额度 15000或自定义 - 实现购物商城,买东西加入 购物车,调用信用卡接口结账 - 可以提现,手续费5% - 支持多账户登录 - 支持账户间转账 - 记录 ...
随机推荐
- Elasticsearch之集群角色类型
角色划分 在Elasticsearch中,有很多角色,常用的角色有如下: Master Node:主节点 Master eligible nodes:合格节点 Data Node:数据节点 Coord ...
- 国产电脑可较为流畅运行的Windows系统
系统是Windows2003,内置了WPS和IE8,使用QEMU TCG运行,速度慢,凑合能用. 使用前先sudo apt install qemu-system-x86,把压缩包中的2003.qco ...
- CentOS 7.9 安装 rocketmq-4.9.2
一.CentOS 7.9 安装 rocketmq-4.9.2 地址: https://rocketmq.apache.org https://github.com/apache/rocketmq ht ...
- P2680 [NOIP2015 提高组] 运输计划 (树上差分-边差分)
P2680 题目的大意就是走完m条路径所需要的最短时间(边权是时间), 其中我们可以把一条边的权值变成0(也就是题目所说的虫洞). 可以考虑二分答案x,找到一条边,使得所有大于x的路径都经过这条边(差 ...
- 洛谷P7960 [NOIP2021] 报数 (筛法)
禁止报的数的生成规则与埃式筛法类似,考虑用筛法预处理可以报出的数字列表和不可报出的数字,从而 O(1) 回答每一组询问. 用check函数判断数字中是否含有7,用nx[i]记录数字i的下一个合法数. ...
- SpringBoot(三) - Slf4j+logback 日志,异步请求,定时任务
1.Slf4j+logback 日志 SpringBoot框架的默认日志实现:slf4j + logback: 默认日志级别:info,对应了实际生产环境日志级别: 1.1 日志级别 # 常见的日志框 ...
- python2与python区别汇总
目录 输入与输出 range使用区别 字符编码区别 输入与输出 python2与python3中两个关键字的区别 python2中 input方法需要用户自己提前指定数据类型 写什么类型就是什么类型 ...
- List接口中的常用方法
void add(int index, Object ele):在index位置插入ele元素boolean addAll(int index, Collection eles):从index位置开始 ...
- java连接数据库加载驱动到java项目
java连接数据库 package com.cook.zheng; import java.sql.Connection; import java.sql.DriverManager; public ...
- 创建Vue工程常用的命令
创建一个vue项目的步骤 1.创建一个名称为myapp的工程 vue init webpack myapp 2.进入工程目录 cd myapp 3.安装 vue-router npm install ...