• 项目开发流程

    1.需求分析:品经理与架构师,根据客户的需求,理出一套比较容易编写的流程
    2.架构设计:架构师根据具体的业务需求选择 具体的开发编程语言与项目框架,所需要的数据库(主库,从库)。与开发目录规范,项目功能划分。项目的报价
    3.分组开发:将项目拆分成多个小项目交给不同开发部门下的多个程序员
    4.提交测试:测试人员对项目进行全方面的测试
    5.交付上线:打包给运维人员进行维护
  • 项目需求分析

    大致功能如下(可拓展):
    1.注册功能:支持多账户注册
    2.登陆功能
    3.查看余额
    4.提现功能:提现需要设置手续费,比例可以由管理员定义
    5.充值功能
    6.转账功能:支持给已注册用户转账
    7.查看流水
    8.添加购物车
    9.查看购物车
    10.结算购物车
    11.管理员功能
  • 项目涉及内容

1.数据类型内置方法
2.函数的基本用法及特点
3.内置模块,自定义模块用法
  • 项目架构设计

    三层架构
    1.用户交互层:也称展示层,主要功能是和用户交互,展示功能
    2.核心逻辑层:也称逻辑层,存放所有逻辑判断功能
    3.数据处理层:数据层,做数据的增删改查并且和系统交互,返回给第二层
  • 项目目录搭建

1.bin
start.py # 存放启动脚本
2.conf
settings.py # 存放配置文件
3.lib
common # 存放公共功能
4.log # 存放项目日志
5.core
src.py # 展示层
6.interface # 核心逻辑层
shop_interface # 购物车接口
bank_interface # 银行接口
user_interface # 用户接口
admin_interface # 管理员接口 db
db_handlerl.py # 数据处理层
readme # 说明
  • 项目功能搭建

    空函数 功能字典 循环匹配
  • 框架搭建(src.py文件代码:)

is_login= {'username':''}  # 全局变量 保存登录信息

# 用户注册
def register():
pass
# 用户登录
def login():
pass # 查看余额
def check_balance():
pass # 余额提现
def Withdraw():
pass # 账户充值
def pay():
pass # 转账
def tranfer():
pass # 查看流水
def check_flow():
pass # 添加购物车
def add_shop_car():
pass # 查看购物车
def check_shop_car():
pass # 结算
def pay_shop_car():
pass # 管理员
def admin():
pass # 功能字典
func_dict = {
'1': register,
'2': login,
'3': look_balance,
'4': Withdraw,
'5': pay,
'6': tranfer,
'7': cheak_water,
'8': add_shop_car,
'9': view_shop_car,
'10': clear_shop_car,
'11': admin } while True:
print("""
1.用户注册
2.登录功能
3.查看余额
4.余额提现
5.账户充值
6.金额转账
7.查看流水
8.添加购物车
9.查看购物车
10.结算购物车
11.管理员功能
""") choice = input('请输入功能编号>>>:').strip()
if choice in func_dict:
func_name = func_dict.get(choice)
func_name()
else:
print('好好输!')
  • 启动文件(start.py文件代码)
import os
import sys base_dir = os.path.dirname(os.path.dirname(__file__)) # 1.找到根目录
sys.path.append(base_dir) # 2.在将根目录添加至环境变量,不受用户和路径限制 if __name__ == '__main__':
from core import src
src.run() # 3.调用run()函数,开始展示功能
  • 配置文件(setting.py文件代码)
import os

#  获取根目录路径,如果不存在则创建
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
DB_DIR = os.path.join(BASE_DIR, 'db')
if not os.path.exists(DB_DIR):
os.mkdir(DB_DIR) MONETY_RATE = 0.05 # 定义手续费费率,因为不常修改所以放在配置文件大写 # 记录日志字典
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]' # 其中name为getlogger指定的名字
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' LOG_DIR = os.path.join(BASE_DIR, 'log')
if not os.path.isdir(LOG_DIR):
os.mkdir(LOG_DIR)
LOGFILE_PATH = os.path.join(LOG_DIR, 'ATM.log') LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': standard_format
},
'simple': {
'format': simple_format
},
},
'filters': {}, # 过滤日志
'handlers': {
# 打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'simple'
},
# 打印到文件的日志,收集info及以上的日志
'default': {
'level': 'DEBUG',
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件
'formatter': 'standard',
'filename': LOGFILE_PATH, # 日志文件
'maxBytes': 1024 * 1024 * 5, # 日志大小 5M
'backupCount': 5,
'encoding': 'utf-8', # 日志文件的编码,再也不用担心中文log乱码了
},
},
'loggers': {
# logging.getLogger(__name__)拿到的logger配置
'': {
'handlers': ['default', 'console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
'level': 'DEBUG',
'propagate': True, # 向上(更高level的logger)传递
}, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
# '购物车记录': {
# 'handlers': ['default','console'], # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
# 'level': 'WARNING',
# 'propagate': True, # 向上(更高level的logger)传递
# }, # 当键不存在的情况下 (key设为空字符串)默认都会使用该k:v配置
},
}
  • 公共文件(common文件代码)
"""
代码中加密,装饰器,判断数字是否符合要求,日志都是公共功能,因此放在common中
"""
import hashlib
import logging
import logging.config
from core import src
from conf import settings def get_hash(user_pwd):
md5 = hashlib.md5()
md5.update(user_pwd.encode('utf8'))
return md5.hexdigest() def login_auth(func):
def inner(*args, **kwargs):
if src.is_login.get('username'):
res = func(*args, **kwargs)
return res
else:
print('您尚未登陆,请先登陆')
src.login()
return inner def get_num(target_money):
try:
target_money = float(target_money)
except:
return False, '请输入整数或小数'
else:
return True, target_money def get_logger(msg):
logging.config.dictConfig(settings.LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger(msg)
return logger1
  • 数据库操作相关代码(db_handler文件代码)
"""
此文件主要用于数据库文件的存取,存取需要多次用到,所以直接封成函数放在数据库操作文件中方便使用
"""
import os
import json
from conf import settings def save(user_dict):
user_name = user_dict.get('username')
user_file_path = os.path.join(settings.DB_DIR, f'{user_name}.json')
with open(user_file_path, 'w', encoding='utf8') as f:
json.dump(user_dict, f, ensure_ascii=False) def select(user_name):
user_file_path = os.path.join(settings.DB_DIR, f'{user_name}.json')
if os.path.exists(user_file_path):
with open(user_file_path, 'r', encoding='utf8') as f:
return json.load(f)
  • 注册功能
"""
注册功能应首先在第一层获取用户输入,简单逻辑判断之后传给第二层,进行逻辑判断,涉及是否已注册功能及存取需要用到db_handler中的函数
"""
src代码:
def register():
user_name = input('请输入您的用户名>>>:').strip() # 1.获取用户输入
user_pwd = input('请输入您的密码>>>:').strip()
confirm_pwd = input('请再次输入您的密码>>>:').strip()
if not user_pwd == confirm_pwd: # 2.将用户两次输入的密码进行对比,如果不一致则退出运行,重新选择任务编号
print('两次密码输入不一致,请再次输入')
return
flag, msg = user_interface.register_interface(user_name, user_pwd) # 3.用两个变量名接收interface层注册函数的返回值
"""
由于本项目部分函数需要返回两个返回值,因此统一用两个变量名来接收函数的返回值,部分函数返回值可能用不上,只是为了统一格式
"""
print(msg) user_interface代码:
def register_interface(user_name, user_pwd): # 1.定义注册接口函数
user_dict = db_handler.select(user_name) # 2.通过db_handler中的select()函数获取函数的返回值
if user_dict: # 3.如果有返回值,说明用户已存在,结束注册功能
return False, f'用户名{user_name}已注册'
user_pwd = common.get_hash(user_pwd) # 4.给传入的密码加密
user_dict = { # 5.构造字典
'username': user_name,
'password': user_pwd,
'balance': 15000,
'shop_car': {},
'is_lock': False,
'water_flow': []
}
db_handler.save(user_dict) # 6.调用db_handler中的save()函数来保存构造的字典
logger.info(f'用户{user_name}注册成功')
return True, f'用户{user_name}注册成功' # 7.返回返回值
  • 登陆功能
src代码:
def login():
user_name = input('请输入您的用户名>>>:').strip() # 1.获取用户输入
user_pwd = input('请输入您的密码>>>:').strip()
flag, msg = user_interface.login_inrterface(user_name, user_pwd)
if flag: # 3.用两个变量名接收interface层注册函数的返回值
is_login['username'] = user_name # 4.记录登录状态
print(msg) interface代码:
def login_inrterface(user_name, user_pwd):
user_dict = db_handler.select(user_name) # 1.通过select()函数来返回用户字典或None
if not user_dict: # 2.逻辑判断:如果没有返回字典,说明用户未注册,将合适的返回值返回给用户
return False, f'用户{user_name}未注册'
user_pwd = common.get_hash(user_pwd) # 3.如果用户已注册,先获取加密后的密码
if user_pwd == user_dict.get('password'): # 4.将用户输入后的密码和存储的密码进行对比(都是加密后的密码)
logger.info(f'用户{user_name}登陆成功')
return True, '登陆成功'
return False, '密码错误' # 5.如果对比不成功返回布尔值和密码错误
  • 查看余额

src代码:
@common.login_auth # 1.通过添加装饰器来限制用户执行该功能前必须先登陆
def check_balance():
user_name = is_login.get('username') # 2.因为用户登录成功时修改了登录状态,所以可以直接通过is_login拿到用户的用户名
flag, msg = bank_interface.check_balance_interface(user_name) # 3.用2个变量名来接收interface()函数的返回值
print(msg) # 4.打印返回的信息 interface代码:
def check_balance_interface(username):
user_dict = db_handler.select(username) # 1.通过传入的用户名从select()函数中通过返回值拿到用户字典
user_balance = user_dict.get('balance') # 2.获取到用户的余额
logger.debug(f'用户{username}查看了自己的账户余额')
return True, f'尊敬的{username},您的账户余额为{user_balance}' # 3.将布尔值True和账户余额返回给src中的msg
  • 提现功能
src代码:
@common.login_auth
def withdraw():
user_name = is_login.get('username') # 1.通过is_login拿到用户的用户名
target_money = input('请输入您想要提现的金额>>>:').strip() # 2.获取用户提现金额
flag, msg = bank_interface.withdraw_interface(user_name, target_money) # 3.用2个变量名来接收interface()函数的返回值
print(msg) interface代码:
def withdraw_interface(username, target_money):
flag, value = common.get_num(target_money) # 1.通过common中的get_num()函数来判断数字是否符合要求
if not flag: # 2.如果不符合将返回值返回给第一层,重新输入
return False, '请输入符合要求的金额'
user_dict = db_handler.select(username) # 3.通过select()获取用户字典,因为此时是从is_login获取到的用户名,所以字典肯定存在,无需判断
user_balance = user_dict.get('balance') # 4.获取用户余额
if user_balance >= value * (1 + settings.MONETY_RATE): # 5.判断用户余额是否大于提现金额加手续费,因为手续费不常修改,所以放在settings中大写
user_dict['balance'] -= value * (1 + settings.MONETY_RATE) # 6.修改用户字典中的余额,考虑手续费
ctime = time.strftime('%Y-%m-%d %H:%M:%S') # 7.记录时间,用于记录流水
user_dict['water_flow'].append(
f'{username}于{ctime}提现{value},手续费{value * settings.MONETY_RATE},账户余额{user_dict.get("balance")}')
db_handler.save(user_dict) # 8.添加流水
logger.debug(f'用户{username}提现{value},手续费{value * settings.MONETY_RATE},账户余额{user_dict.get("balance")}')
return True, f'尊敬的{username}成功提现{value},手续费{value * settings.MONETY_RATE},账户余额{user_dict.get("balance")}'
return False, f'尊敬的{username}, 您的账户余额不足,无法提现' # 9.通过逻辑判断返回不同的返回值
  • 充值功能
src代码:
@common.login_auth
def pay_back():
user_name = is_login.get('username')
target_money = input('请输入您想充值的金额>>>:').strip()
flag, msg = bank_interface.pay_back_interface(user_name, target_money)
print(msg) interface代码:
def pay_back_interface(user_name, target_money):
flag, value = common.get_num(target_money)
if not flag:
return False, '请输入符合要求的金额数字'
user_dict = db_handler.select(user_name)
user_dict['balance'] += value
ctime = time.strftime('%Y-%m-%d %H:%M:%S')
user_dict['water_flow'].append(f'{user_name}于{ctime}充值{value},账户余额{user_dict.get("balance")}')
db_handler.save(user_dict)
logger.debug(f'用户{user_name}充值{value},账户余额{user_dict.get("balance")}')
return True, f'尊敬的{user_name},您于{ctime}成功充值{value},账户余额{user_dict.get("balance")}'
  • 转账功能
src代码:
@common.login_auth
def transfer():
user_name = is_login.get('username')
target_name = input('请输入您想转账的用户名>>>:').strip()
target_money = input('请输入您想转账的金额>>>:').strip()
flag, msg = bank_interface.transfer_interface(user_name, target_name, target_money)
print(msg) interface代码:
def transfer_interface(user_name, target_name, target_money):
target_dict = db_handler.select(target_name)
if not target_dict:
return False, f'用户{target_name}未注册'
flag, value = common.get_num(target_money)
if not flag:
return False, '请输入符合要求的数字'
user_dict = db_handler.select(user_name)
if user_dict.get('balance') >= value:
user_dict['balance'] -= value
ctime = time.strftime('%Y-%m-%d %H:%M:%S')
user_dict['water_flow'].append(
f'尊敬的{user_name},您于{ctime}给{target_name}转账{value},账户余额{user_dict.get("balance")}')
target_dict['balance'] += value
target_dict['water_flow'].append(
f'尊敬的{target_name},{user_name}于{ctime}给您转账{value},账户余额{target_dict.get("balance")}')
db_handler.save(user_dict)
db_handler.save(target_dict)
logger.debug(
f'用户{user_name}给{target_name}转账{value},{user_name}账户余额{user_dict.get("balance")},{target_name}账户余额{target_dict.get("balance")}')
return True, f'尊敬的{user_name}, 您于{ctime}给{target_name}转账{value},账户余额{user_dict.get("balance")}'
return False, f'您的账户余额不足,无法转账'
  • 查看流水
src代码:
@common.login_auth
def check_flow():
user_name = is_login.get('username')
flag, msg = bank_interface.check_flow_interface(user_name)
if flag:
for data in msg:
print(data)
else:
print(msg) interface代码:
def check_flow_interface(username):
user_dict = db_handler.select(username)
if user_dict.get('water_flow'):
logger.debug(f'用户{username}查看了流水')
return True, user_dict.get('water_flow')
else:
logger.debug(f'用户{username}查看了流水')
return False, '您暂无流水'
  • 添加购物车
"""
添加购物车主要功能可以写在第二层,第一层主药方用户交互功能
"""
src代码:
@common.login_auth
def add_shop_car():
user_name = is_login.get('username')
flag, msg = shop_interface.add_shop_car_interface(user_name)
print(msg) interface代码:
def add_shop_car_interface(user_name):
tem_list = {}
while True:
good_list = [
['挂壁面', 3],
['印度飞饼', 22],
['极品木瓜', 666],
['土耳其土豆', 999],
['伊拉克拌面', 1000],
['董卓戏张飞公仔', 2000],
['仿真玩偶', 10000]
]
for i, j in enumerate(good_list, start=1):
print(f"""
商品编号:{i} | 商品名称:{j[0]} | 商品单价:{j[1]}
""")
choice = input('请输入您的商品编号(q)>>>:').strip()
if choice == 'q':
user_dict = db_handler.select(user_name)
shop_car = user_dict.get('shop_car')
for i in tem_list:
if i in shop_car:
shop_car.get(i)[0] += tem_list.get(i)[0]
else:
shop_car[i] = tem_list.get(i)
user_dict['shop_car'] = shop_car
db_handler.save(user_dict)
logger.info(f'用户{user_name}添加了购物车')
return True, f'用户{user_name}购物车添加完毕' if not choice.isdigit():
print('商品编号必须是纯数字')
continue
choice = int(choice)
if not choice in range(1, len(good_list) + 1):
print('没有该商品')
continue
num = input(f'请输入您购买{good_list[choice - 1][0]}的数量>>>:')
if not num.isdigit():
print('商品数量必须是纯数字')
continue
num = int(num)
target_list = good_list[choice - 1]
target_good = target_list[0]
if target_good in tem_list:
tem_list.get(target_good)[0] += num
else:
tem_list[target_good] = [num, target_list[1]]
  • 查看购物车功能
src.py代码:
@common.login_auth
def check_shop_car():
user_name = is_login.get('username')
flag, msg = shop_interface.check_shop_car_interface(user_name)
if flag:
for i in msg:
print(f"""
商品名称:{i} | 商品数量:{msg.get(i)[0]} | 商品单价:{msg.get(i)[1]}
""")
else:
print(msg) interface代码:
def check_shop_car_interface(user_name):
user_dict = db_handler.select(user_name)
shop_car = user_dict.get('shop_car')
if shop_car:
logger.info(f'用户{user_name}查看了购物车')
return True, shop_car
else:
logger.info(f'用户{user_name}查看了购物车')
return False, '您的购物车为空'
  • 结算购物车功能
src代码:
@common.login_auth
def pay_shop_car():
user_name = is_login.get('username')
flag, msg = shop_interface.pay_shop_car_interface(user_name)
print(msg) interface代码:
def pay_shop_car_interface(user_name):
user_dict = db_handler.select(user_name)
shop_car = user_dict.get('shop_car') # {'极品木瓜': [9, 666], '伊拉克拌面': [5, 1000]}
current_balance = user_dict.get('balance')
money = 0
for i in shop_car.values(): # i:[9, 666]
money += i[0] * i[1]
if money > current_balance:
return False, f'您的账户余额不足,无法结算'
current_balance -= money
shop_car = {}
user_dict['balance'] = current_balance
user_dict['shop_car'] = {}
user_dict['water_flow'].append(f'{user_name},您本次消费{money},账户余额{user_dict.get("balance")}')
db_handler.save(user_dict)
logger.info(f'用户{user_name}结算了购物车,本次消费{money},账户余额{user_dict.get("balance")}')
return True, f'尊敬的{user_name},您本次消费{money},账户余额{user_dict.get("balance")}'

最新文章

  1. MVC4 遇到问题总结
  2. 中国大学MOOC-陈越、何钦铭-数据结构-2016秋期中考试
  3. 利用python3.5 +TK 开发股票自动交易伴侣
  4. Java入门——(2)面对对象(上)
  5. CPU31X-2DP通过DP网络连接远程IO站
  6. Egret学习笔记 (Egret打飞机-6.实现敌机飞起来)
  7. Oracle timestamp类型转换成date类型
  8. H5 id选择器和class选择器
  9. 十六、Mediator 仲载者设计模式
  10. Kotlin入门(19)Android的基础布局
  11. 源代码管理工具(下)-SVN目录结构
  12. C#中的预处理指令详解
  13. ios App 文件夹
  14. word文档批量合并工具
  15. javascript004_ECMA5数组新特性
  16. django ajax增 删 改 查
  17. leetcode-longest palindromic substring-by 1337c0d3r
  18. Asp ose.Tota l for .NET 2015
  19. VS进行调试时IIS Express显示Access Define-坑爹的腾讯TGP助手
  20. Maven(2)-坐标和依赖

热门文章

  1. Linux备份文件加“时间”命令
  2. 嵌入式-C语言基础:数组得初始化
  3. spring运行报500 bean不存在
  4. hyperworks2021位安装教程
  5. 在 Solidity 中 ++i 为什么比 i++ 更省 Gas?
  6. npm安装hexo报错
  7. i春秋Vld
  8. Selenium4+Python3系列(九) - 上传文件及滚动条操作
  9. Java开发学习(四十四)----MyBatisPlus查询语句之查询条件
  10. 用excel表画一个乐高