一、软件开发的目录规范
ps:在公司里面一般会直接创建一个项目,start.py会直接放在根目录下,这样用起来更加方便
#执行文件bin---->start.py------ps:只要短短几行,不要长篇写代码
from core import src
src.run()
#配置conf---->settings
import os
print(__file__) # D:python全栈15期day17ATMconfsettings.py
BASE_DIR=os.path.dirname(os.path.dirname(__file__)) # D:python全栈15期day17ATM
log_path = os.path.join(BASE_DIR,'log','access.log')
ps:__file__指的是当前文件的绝对路径
os.path
sys.path
os.environ把想要在全局看的加载到环境变量
#核心代码core---->src.py
from lib import common
def shop():
print("购物功能")
common.logger("xxx购买了一堆垃圾")
def repay():
print("支付功能")
common.logger("fzh支付了100亿")
def withdraw():
print('提现')
common.logger("fzh提现了200亿")
func_dic = {
'1': [shop, "购物功能"],
'2': [repay, "支付功能"],
'3': [withdraw, "提现功能"],
}
def run():
while True:
for k in func_dic:
print('%s---%s' % (k, func_dic[k][1]))
choice = input("请输入您的操作编号/输入0退出: ").strip()
if choice == '0':
break
if choice in func_dic:
func_dic[choice][0]()
else:
print('指令错误,请重新输入')
#共享文件夹lib---->common.py
import time
from conf import settings
def logger(msg):
with open(settings.log_path, mode='at', encoding='utf-8') as f:
log_format = "%s %s
" % (time.strftime('%Y-%m-%d %H:%M:%S'), msg)
f.write(log_format)
#数据---->db
#日志文件log---->自动生成access.log
二、ATM购物车文件
程序的说明文件 --->readme
程序的入口文件/启动文件--->start.py
配置文件夹conf --->settings.py
公共方法文件lib --->common.py
接口文件夹interface--->user.py用户接口文件
--->shop.py购物接口文件
--->bank.py银行接口文件
用户功能文件夹core --->scr.py视图文件
数据处理文件夹db --->da_handler.py数据处理功能文件
日志存放目录log --->access.log自动生成日志
1、目录规范
2、readme
# ATM + 购物车项目 # 一个项目是如何从无到有的 # 1、需求分析(需要关注) 额度 15000 或 自定义 ---> 注册功能 实现购物商城,买东西加入 购物车,调用 信用卡接口 结账 ----> 购物功能、支付功能 可以提现,手续费5% ---> 提现功能 支持多账户登录 ---> 登录功能 支持账户间转账 ---> 转账功能 记录消费流水 ---> 记录流水功能 提供还款接口 ---> 还款功能 ATM记录操作日志 ---> 记录日志功能 提供管理接口,包括添加账户、修改用户额度,冻结账户等。。。 ---> 管理员功能(添加账户、修改用户额度,冻结账户) 用户认证用装饰器 ---> 登录认证装饰器‘ # 用户界面允许用户能选择的功能 1.注册功能 2.登录功能 3.查看余额 4.提现功能 5.还款功能 6.转账功能 7.查看流水 8.购物功能 9.查看购物车功能 10.管理员功能 - 添加账户、修改用户额度,冻结账户 # 2、程序的架构设计(需要关注) - 三层架构(*******) - 视图层: 专门用于与用户交互; - 展示功能给用户看、接收用户输入的数据、将功能返回的结果展示给用户看的; - 接口层: 专门做业务逻辑的处理; - 接收到用户输入的数据,进行逻辑判断,然后返回判断后的结果给视图层; - 数据层: 专门做数据的处理 - 增加数据 - 删除数据 - 更新数据 - 查看数据 # 3、分任务开发 - 项目经理:(项目的负责人) - UI(1-2人): 界面设计(app端的界面/web界面)。 - 前端(1-2人): 拿到UI的设计图纸,开发页面。 - 后端(2-3人): 开发业务逻辑 - 运维(1人): 拿到开发好的代码,部署再 “服务器” 中,上线运行 # 4、测试软件 # 5、上线运营
3、start.py
# 启动程序入口 # 1.将当前ATM项目工程,添加解释器的环境变量 import os # 与操作系统进行交互 import sys # 与解释器进行交互 # 1) 获取ATM的目录路径 base_path = os.path.dirname(__file__) # 2) 将项目路径添加到解释器的环境变量中 sys.path.append(base_path) # 3) 将视图层中的执行函数,引用到当前位置执行 from core import src if __name__ == '__main__': # 执行src模块中的run函数 src.run()
4、conf---->settings
# 配置文件(常量) import os # ATM根目录路径 # D:python全栈15期day18ATM BASE_PATH = os.path.dirname(os.path.dirname(__file__)) # DB目录路径 # D:python全栈15期day18ATMdb DB_PATH = os.path.join(BASE_PATH, 'db')
5、core--->src
# 视图层 from interface import user_interface from interface import bank_interface from lib import common # 专门用于记录用户是否登录,登录状态 user_info = { 'user': None } # 拆分三层架构版本 def register(): while True: # 1) 让用户输入用户名与密码 username = input('请输入用户名: ').strip() password = input('请输入密码: ').strip() re_password = input('请输入密码: ').strip() # 2)小的逻辑判断 if password == re_password: # 3) 再视图层中调用注册接口,将用户与密码传递给注册接口做 核心逻辑的处理 # flag, msg = (False, '用户已存在,请重新输入') flag, msg = user_interface.register_interface(username, password) # True, f'用户[{username}]注册成功' if flag: print(msg) break # False, '用户已存在,请重新输入' else: print(msg) else: print('两次密码不一致,请重新输入!') # 2.登录功能 def login(): while True: # 1) 让用户输入用户名与密码 username = input('请输入用户名: ').strip() password = input('请输入密码: ').strip() # 3) 再视图层中调用 登录接口 ,将用户与密码传递给登录接口做 核心逻辑的处理 flag, msg = user_interface.login_interface(username, password) # True, f'用户[{username}]登录成功' if flag: print(msg) user_info['user'] = username break # False, '用户已存在,请重新输入' else: print(msg) # 3.查看余额 @common.login_auth def check_bal(): # 直接调用查看余额接口层,获取数据 bal = user_interface.check_bal_interface(user_info.get('user')) print(f'当前用户的余额为:[{bal}]') # 4.提现功能 @common.login_auth def withdraw(): while True: # 1) 输入需要提现的金额 balance = input('请输入需要提现的金额:').strip() # 小的逻辑判断,判断是否是数字,若是数字则转为int类型 if not balance.isdigit(): print('请输入数字类型!') continue # str ---> int balance = int(balance) # 2) 调用提现接口 # flag, msg = (True, f'提现[{money}]成功! 手续费为:[{money2 - money}]') flag, msg = bank_interface.withdraw_interface(user_info.get('user'), balance) # 3)打印接口返回的结果 if flag: print(msg) break else: print(msg) # 5.还款功能 @common.login_auth def repay(): while True: # 1) 让用户输入还款金额 money = input('请输入需要还款的金额: ').strip() # 2) 小的逻辑判断,判断是否是数字,若是数字则转为int类型 if not money.isdigit(): print('请输入数字类型!') continue money = int(money) # 3) 调用还款接口 msg = bank_interface.repay_interface(user_info.get('user'), money) print(msg) break # 6.转账功能 @common.login_auth def transfer(): pass # 7.查看流水 @common.login_auth def check_flow(): pass # 8.购物功能 @common.login_auth def shopping(): pass # 9.查看购物车功能 @common.login_auth def check_shop_car(): pass # 10.管理员功能 @common.login_auth def admin(): pass # 函数功能字典 func_dic = { '1': register, '2': login, '3': check_bal, '4': withdraw, '5': repay, '6': transfer, '7': check_flow, '8': shopping, '9': check_shop_car, '10': admin, } # 提供给用户选择的函数 def run(): while True: print(''' 1.注册功能 2.登录功能 3.查看余额 4.提现功能 5.还款功能 6.转账功能 7.查看流水 8.购物功能 9.查看购物车功能 10.管理员功能 ''') choice = input('请输入功能编号: ').strip() # 判断用户选择的编号是否再函数功能字典中 if choice not in func_dic: print('编号有误,请重新输入!') continue # func_dic.get('1') ---> register() func_dic.get(choice)()
# 1.注册功能 # 不分层版本 # def register(): # while True: # username = input('请输入用户名: ').strip() # password = input('请输入密码: ').strip() # re_password = input('请输入密码: ').strip() # # if password == re_password: # # # 组织用户的数据,转成json数据 --> json_str 保存到文件中 # # 逻辑处理 # user_dic = { # 'name': username, # 'pwd': password, # 'balance': 15000, # 'flow': [], # # 'shop_car': {'商品名称': ['商品数量', '单价']} # 'shop_car': {}, # 'locked': False # } # # D:python全栈15期day18ATMdb ank.json # # 以每个注册 “用户的名字” 作为json文件名 # user_path = os.path.join(settings.DB_PATH, '%s.json' % username) # # # 判断当前注册用户是否存在,os.path.exists(需要判断的文件路径) # if os.path.exists(user_path): # print('用户已存在,请重新输入!') # continue # # with open(user_path, 'w', encoding='utf-8') as f: # # dict ---> json_str ---> f.write(json_str) ----> json文件中 # json.dump(user_dic, f) # # 文件刷新 # f.flush() # # print(f'用户[{username}]注册成功') # break # else: # print('两次密码不一致,请重新输入!')
6、db---->handler
# 数据层 import json from conf import settings import os # 1、查看数据 def select(username): # 用户json文件的路径 user_path = os.path.join(settings.DB_PATH, '%s.json' % username) # 判断当前注册用户是否存在,os.path.exists(需要判断的文件路径) if os.path.exists(user_path): # 读取文件中的数据 with open(user_path, 'r', encoding='utf-8') as f: # f.read() ---> json_str ---> python user_dic = json.load(f) return user_dic # 2、保存数据 def save(user_dic): # 用户json文件的路径 user_path = os.path.join(settings.DB_PATH, '%s.json' % user_dic['name']) # 将数据写入文件中 with open(user_path, 'w', encoding='utf-8') as f: # dict ---> json_str ---> f.write(json_str) ----> json文件中 json.dump(user_dic, f) # 文件刷新 f.flush()
7、interface
bank_interface.py
# 银行功能接口 from db import db_handler # 提现接口 def withdraw_interface(username, money): user_dic = db_handler.select(username) # 可以提现,手续费5% # 1) 判断用户账户的金额是否,大于等于 提现金额 + 5%手续费 # 提现金额 + 5%手续费 money + money * 0.05 money2 = money * 1.05 if user_dic.get('balance') >= money2: # 给当前用户字典金额减钱 user_dic['balance'] -= money2 db_handler.save(user_dic) return True, f'提现[{money}]成功! 手续费为:[{money2 - money}]' else: return False, '余额不足,快去充钱!' # 还款接口 def repay_interface(username, money): # 1) 先将当前用户字典取出来 user_dic = db_handler.select(username) # 2)直接加钱 user_dic['balance'] += money # 3)再更新数据 db_handler.save(user_dic) return f'还款[{money}]成功!'
user_interface.py
# 用户功能接口 from db import db_handler # 注册接口 def register_interface(username, password): # 逻辑处理 ---> 接口层 # 1) 去数据处理层获取用户数据 # user_dic ---> 用户字典 / None user_dic = db_handler.select(username) # 2) 若user_dic有数据,则代表用户存在,返回用户已存在,请重新输入给 if user_dic: return False, '用户已存在,请重新输入' # ---》 return (False, '用户已存在,请重新输入') # 3) 若用户不存在,则可以注册 # 组织用户的数据,转成json数据 --> json_str 保存到文件中 user_dic = { 'name': username, 'pwd': password, 'balance': 15000, 'flow': [], # 'shop_car': {'商品名称': ['商品数量', '单价']} 'shop_car': {}, 'locked': False } # 4) 调用数据层中的保存数据功能save,将字典传递过去进行数据的保存 db_handler.save(user_dic) # 5) 返回注册结果给用户视图层 return True, f'用户[{username}]注册成功' # 登录接口 def login_interface(username, password): # 1) 先去数据层,获取用户字典数据 user_dic = db_handler.select(username) # 2) 判断用户是否存在,若存在则校验密码 if user_dic: if password == user_dic.get('pwd'): return True, f'用户[{username}]登录成功!' else: return False, '密码错误,请重新输入' # 3) 若不存在,则返回 错误信息给视图层 else: return False, '用户不存在,请重新输入' # 查看余额接口 def check_bal_interface(username): user_dic = db_handler.select(username) return user_dic.get('balance')
8、lib---->common.py
# 此处写公共方法 # 登录认证装饰器模板 def login_auth(func): # 解决循环导入问题 from core import src def inner(*args, **kwargs): # 判断用户的登录状态,若有值代表已登录,通过校验 if src.user_info.get('user'): res = func(*args, **kwargs) return res else: src.login() return inner
9、log
日志