目录
- 一、项目视图分析
- 二、文件结构分析
- 三、完整代码
- 1.start.py
- 2.conf
- 3.core
- 4.interface
- 5.db
- 6.lib
- 7.readme
一、项目视图分析
通过上图,我们可以看到,一个完整的项目,基本包括三个部分:用户视图层、接口层、数据处理层,其中,用户视图层是用来接收用户的数据输入的,比如:有户名,密码;接口层是要接收用户视图层传来的数据,然后做判断:名字是否存在、密码是否正确,这就要求接口层调用数据处理层的方法;数据处理层就需要接收接口层的参数,把接口层需要的增、删、改、查的数据结果返回给接口层,接口层再把判断的结果返回给用户层。
二、文件结构分析
文件主要有以下几个部分:conf(setting.py-参数配置,比如:日志文件的配置、路径等)、core(src.py\admin.py-用户视图层,分为图通用户和管理员)、interface(接口层,里面有很多接口:用户接口,购物接口,银行接口,管理员接口,分这么细是为了“解耦合”)、db(用户数据存放;数据处理层:主要负责数据的增、删、改、查)、lib(公共方法:比如登录功能的装饰器)、log(日志文件)、readme(文档说明)、strat启动
三、完整代码
1.start.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:59 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: start.py | |
''' | |
''' | |
程序的入口 | |
''' | |
import sys | |
import os | |
#添加解释器的环境变量 | |
sys.path.append( | |
os.path.dirname(__file__) | |
) | |
#导入用户视图层 | |
from core import src | |
# 开始执行项目函数 | |
if __name__ == '__main__': | |
# 1.先执行用户视图层 | |
src.run() |
2.conf
-settings.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:49 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: settings.py | |
''' | |
''' | |
存放配置信息 | |
''' | |
import os | |
#获取项目根目录路劲 | |
BASE_PATH = os.path.dirname( | |
os.path.dirname(__file__) | |
) | |
# 获取user_data文件夹目录路径 | |
USER_DATA_PATH = os.path.abspath(os.path.join(BASE_PATH, 'db','user_data')) | |
#USER_DATA_PATH2 = os.path.join(BASE_PATH, 'db','user_data').replace('\\','/') | |
username = 'rice' | |
user_path = os.path.abspath(os.path.join(USER_DATA_PATH, f'{username}.json')).replace('\\','/') | |
""" | |
logging配置 | |
""" | |
BASE_PATH2 = os.path.dirname(os.path.dirname(__file__)) | |
logfile_dir = os.path.abspath(os.path.join(BASE_PATH2,'log')).replace('\\','/') | |
logfile_name = 'atm.log' | |
#如果不存在定义的日志目录就创建一个 | |
if not os.path.isdir(logfile_dir): | |
os.mkdir(logfile_dir) | |
#log文件的全路径 | |
logfile_path = os.path.join(logfile_dir, logfile_name).replace('\\','/') | |
standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \ | |
'[%(levelname)s][%(message)s]' | |
simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s' | |
test_format = '%(asctime)s] %(message)s' | |
# 3、日志配置字典 | |
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': 'simple', | |
# 可以定制日志文件路径 | |
# BASE_DIR = os.path.dirname(os.path.abspath(__file__)) # log文件的目录 | |
# LOG_PATH = os.path.join(BASE_DIR,'a1.log') | |
'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', # loggers(第一层日志级别关限制)--->handlers(第二层日志级别关卡限制) | |
'propagate': True, # 默认为True,向上(更高level的logger)传递,通常设置为False即可,否则会一份日志向上层层传递 | |
}, | |
}, | |
} | |
if __name__ == '__main__': | |
print(user_path) |
3.core
-src.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:51 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: src.py | |
''' | |
''' | |
用户视图层 | |
''' | |
from interface import user_interface | |
from lib import common | |
from interface import bank_interface | |
from interface import shop_interface | |
#全局变量,记录用户是否已登录 | |
login_user = None | |
# 1.注册功能 | |
def register(): | |
while True: | |
# 1)让用户输入用户名和密码校验 | |
username = input('请输入用户名:').strip() | |
password = input('请输入密码:').strip() | |
re_password = input('请确认密码:').strip() | |
#可以输入自定义的金额 | |
# 小的逻辑错误:比如两次密码是否一致 | |
if password == re_password: | |
#2)调用接口层的注册接口,将用户名与密码交给接口层来进行处理 | |
#一个元祖 | |
flag, msg = user_interface.register_interface(username, password) | |
# 3)根据flag判断用户注册是否成功,用于控制break | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
# 2.登录功能 | |
#成功登录了之后,一定会修改全局变量:login_user | |
def login(): | |
#登录视图 | |
while True: | |
#1)让用户输入用户名和密码 | |
username = input('请输入用户名:').strip() | |
password = input('请输入密码:').strip() | |
#2)调用接口层,将数据传给登录接口 | |
flag, msg = user_interface.login_interface(username, password) | |
if flag: | |
print(msg) | |
global login_user | |
login_user = username | |
break | |
else: | |
print(msg) #有一个小bug,输入错误后,我想返回主页 #d #成功登录了# | |
# 3.查看余额 | |
def check_balance(): | |
#1.直接调用查看余额接口,获取用户余额 | |
#装饰器本身是有login_user | |
balance = user_interface.check_bal_interface(login_user) | |
print(f'用户{login_user} 账户余额为:{balance}') | |
# 4.提现功能 | |
def withdraw(): | |
while True: | |
#1)让用户输入提现金额 | |
input_money = input('请输入提现金额:').strip() | |
#2)判断用户输入的金额是否是数字 | |
if not input_money.isdigit(): #isdigit()-可以判断字符串 | |
print('请输入') | |
continue | |
#3)用户提现金额,将数据提现的金额交给接口层处理 | |
flag, msg = bank_interface.withdraw_interface(login_user, input_money) | |
if flag: | |
print(msg) | |
break | |
# 5.还款功能 | |
def repay(): | |
''' | |
银行卡还款,无论是信用卡或储蓄卡,是否能任意大小的金额 | |
:return: | |
''' | |
while True: | |
#1) 让用户输入还款金额 | |
input_money = input('请输入需要还款的金额:').strip() | |
#2)判断用户输入的是否是数字 | |
if not input_money.isdigit(): | |
print('请输入正确的金额') | |
continue | |
input_money = int(input_money) | |
#3)判断用户输入的金额大于0 | |
if input_money > 0: | |
#4)调用还款接口 | |
flag, msg = bank_interface.repay_interface(login_user, input_money) | |
if flag: | |
print(msg) | |
break | |
else: | |
print('输入的金额不能小于0') | |
# 6.转账功能 | |
def transfer(): | |
''' | |
1.接收 用户输入的 转账金额 | |
2.接收用户输入的 转账目标用户 | |
:return: | |
''' | |
while True: | |
#1) 让用户输入转账用户与金额 | |
to_user = input('请输入转账目标用户').strip() | |
money = input('请输入转账金额').strip() | |
#2)数据判断 | |
if not money.isdigit(): | |
print('请输入数字') | |
continue | |
money = int(money) | |
if money > 0: | |
#调用转账接口 | |
flag, msg = bank_interface.transfer_interface( | |
login_user,to_user,money | |
) | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
else: | |
print('请输入正确的金额') | |
# 7.查看流水 | |
def check_flow(): | |
#直接调用查看流水接口 | |
flow_list = bank_interface.check_flow_interface(login_user) | |
if flow_list: | |
for flow in flow_list: | |
print(flow) | |
else: | |
print('当前用户没有流水!') | |
# 8.购物功能 | |
def shop(): | |
#不从文件中读取商品数据,直接写 | |
#创建商品列表 | |
# shop_list = { | |
# '0': {'name': '包子', 'price': 30} | |
# } | |
shop_list = [ | |
['包子', 3], #0 | |
['可乐', 5], #1 | |
['book', 200], | |
['pc', 9999], | |
] | |
#初始化当前购物车 | |
shopping_car = {} #{'商品名称':['单价','数量']]} | |
while True: | |
#枚举:enumerate(可迭代对象)--->元祖(可迭代对象的索引,索引对应的值) | |
for index, shop in enumerate(shop_list): | |
shop_name, shop_price = shop | |
print(f'商品编号为{index}, 商品名称{shop_name}, 商品单价:{shop_price}') | |
print(shop) | |
choice = input('请输入商品编号:(是否结账输入y or n)').strip() | |
#让用户根据商品编号进行选择 | |
#输入的是y进行支付结算功能 | |
if choice == 'y': | |
if not shopping_car: | |
print('购物车是空的,不能支付,请重新输入') | |
continue | |
#调用支付接口进行支付 | |
flag, msg = shop_interface.shopping_interface(login_user,shopping_car) | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
#输入的是n添加购物车(把shopping_car添加到json中) | |
elif choice == 'n': | |
#调用添加购物车接口 | |
if not shopping_car: | |
print('购物车是空的,不能添加,请重新输入') | |
continue | |
flag, msg = shop_interface.add_shop_car_interface(login_user, shopping_car) | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
if not choice.isdigit(): | |
print('请输入正确的编号!') | |
continue | |
if not choice.isdigit(): | |
print('请输入正确的编号!') | |
continue | |
choice = int(choice) | |
if choice not in range(len(shop_list)): | |
print('请输入正确的编号!') | |
continue | |
shop_name, shop_price = shop_list[choice] | |
#加入购物车 | |
#判断用户选择的商品是否重复,重复加1 | |
if shop_name in shopping_car: | |
#添加商品数量 | |
shopping_car[shop_name][1] += 1 | |
else: | |
#否则数量默认为1 | |
shopping_car[shop_name] = [shop_price, 1] | |
# 9.查看购物车 | |
def check_shop_car(): | |
shop_car = shop_interface.check_shop_car_interface(login_user) | |
print(shop_car) | |
# 10.管理员功能 | |
def admin(): | |
''' | |
管理员功能:课后作业 | |
:return: | |
''' | |
from core import admin | |
admin.admin_run() | |
# 创建函数功能字典 | |
func_dic = { | |
'1': register, | |
'2': login, | |
'3': check_balance, | |
'4': withdraw, | |
'5': repay, | |
'6': transfer, | |
'7': check_flow, | |
'8': shop, | |
'9': check_shop_car, | |
'10': admin | |
} | |
# 视图层主程序 | |
def run(): | |
while True: | |
print(''' | |
======= ATM + 购物车 ======= | |
1.注册功能 | |
2.登录功能 | |
3.查看余额 | |
4.提现功能 | |
5.还款功能 | |
6.转账功能 | |
7.查看流水 | |
8.购物功能 | |
9.查看购物车 | |
10.管理员功能 | |
========== end ============ | |
''') | |
choice = input('请输入功能编号:').strip() | |
if choice not in func_dic: | |
print('请输入正确的功能编号!') | |
continue | |
func_dic.get(choice)() |
-admin.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/04 11:50 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: admin.py | |
''' | |
from core import src | |
from interface import admin_interface | |
# 添加用户 | |
def add_user(): | |
src.register() | |
# 修改用户额度 | |
def change_balance(): | |
while True: | |
change_user = input('请输入需要修改额度的用户').strip() | |
money = input('请输入需要修改的用户额度:').strip() | |
if not money.isdigit(): | |
print('请输入数字') | |
continue | |
flag, msg = admin_interface.change_balance_interface(change_user, money) | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
break | |
# 输入修改额度 | |
# 输入修改用户 | |
# 调用修改额度接口 | |
# 冻结账户 | |
def lock_user(): | |
while True: | |
change_user = input('请输入需要修改额度的用户:').strip() | |
flag, msg = admin_interface.lock_user_interface(change_user) | |
if flag: | |
print(msg) | |
break | |
else: | |
print(msg) | |
break | |
# 管理员功能字典 | |
admin_dic = { | |
'1': add_user, | |
'2': change_balance, | |
'3': lock_user | |
} | |
def admin_run(): | |
while True: | |
print(''' | |
1、添加用户 | |
2、修改额度 | |
3、冻结账户 | |
''') | |
choice = input('请输入管理员功能编号:').strip() | |
# 判断功能编号是否存在 | |
if choice not in admin_dic: | |
print('请输入正确的功能编号!') | |
continue | |
# 调用用于选择的功能函数 | |
admin_dic.get(choice)() |
4.interface
-user_interface.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:52 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: user_interface.py | |
''' | |
''' | |
逻辑接口层 | |
用户接口 | |
''' | |
import json | |
import os | |
from conf import settings | |
from db import db_handler | |
from lib import common | |
user_logger = common.get_logger('user') | |
#user_logger.setLevel(10) | |
#注册接口 | |
def register_interface(username, password, balance=5000): | |
# 2)查看用户是否存在 | |
#2.1)调用 数据处理层中的select函数,会返回用户字典或None | |
user_dic = db_handler.select(username) | |
#若用户存在,则return,告诉用户重新输入(是通过用户名来判断是否存在的,跟密码没关系) | |
if user_dic: | |
return False, '用户名已存在!' | |
#3)用户不存在,则保存用户数据 | |
#做密码加密 | |
password = common.get_pwd_md5(password) | |
user_dic = { | |
'username': username, | |
'password': password, | |
'balance': balance, | |
# 用于记录用户流水的列表 | |
'flow': [], | |
# 用于记录用户购物车 | |
'shop_car': {}, | |
# locked: 用于记录用户是否被冻结 | |
# False:未冻结 True:已冻结 | |
'locked': False | |
} | |
#3.2)保存数据 | |
db_handler.save(user_dic) | |
msg = f'{username} 用户注册成功' | |
#记录日志 | |
user_logger.info(msg) | |
return True, msg | |
#登录接口 | |
def login_interface(username, password): | |
#1)先查看当前用户数据是否存在 | |
user_dic = db_handler.select(username) | |
#2)判断用户是否存在 | |
#若有冻结用户,则需要判断是否被锁定 | |
if user_dic: | |
if user_dic.get('locked'): | |
return False, '当前用户已被锁定' | |
#给用户输入的密码做一次加密 | |
password = common.get_pwd_md5(password) | |
#3)校验密码是否一致 | |
if password == user_dic.get('password'): | |
msg = f'用户{username}登录成功!' | |
user_logger.info(msg) | |
return True, msg | |
else: | |
msg = f'用户{username}密码错误!' | |
user_logger.warn(msg) | |
return False, msg | |
msg = f'用户{username}不存在!' | |
user_logger.warn(msg) | |
return False, msg | |
#查看余额接口 | |
def check_bal_interface(username): | |
user_dic = db_handler.select(username) | |
return user_dic['balance'] |
-shop_interface.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:53 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: shop_interface.py | |
''' | |
''' | |
商城购物接口层 | |
''' | |
from db import db_handler | |
#商品准备结算接口 | |
def shopping_interface(login_user, shopping_car): | |
#计算消费金额 | |
cost = 0 | |
for price_number in shopping_car.values(): | |
price, number = price_number | |
cost += (price*number) | |
#导入银行接口 | |
from interface import bank_interface | |
#逻辑校验成功后,在调用银行支付接口 | |
flag = bank_interface.pay_interface(login_user,cost) | |
if flag: | |
return True, '支付成功,准备发货' | |
return False, '支付失败,金额不足' | |
#购物车添加接口 | |
def add_shop_car_interface(login_user, shopping_car): | |
#获取当前用户的购物车 | |
user_dic = db_handler.select(login_user) | |
shop_car = user_dic.get('shop_car') | |
#添加购物车 | |
for shop_name, price_number in shopping_car.items(): | |
#每个商品的数量 | |
number = price_number[1] | |
if shop_name in shop_car: | |
user_dic['shop_car'][shop_name] += number | |
db_handler.save(user_dic) | |
print('添加到json成功') | |
else: | |
user_dic['shop_car'].update({shop_name: price_number}) | |
db_handler.save(user_dic) | |
print('添加到json成功') | |
return True, '添加购物车成功' | |
#查看购物车接口 | |
def check_shop_car_interface(username): | |
user_dic = db_handler.select(username) | |
return user_dic.get('shop_car') |
-bank_interface.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:53 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: bank_interface.py | |
''' | |
''' | |
银行先关业务的接口 | |
''' | |
from db import db_handler | |
#提现接口(手续费5%) | |
def withdraw_interface(username, money): | |
#1)先获取用户字典 | |
user_dic = db_handler.select(username) | |
#校验用户的钱是否足够 | |
balance = int(user_dic.get('balance')) | |
#本金+手续费 | |
momey2 = int(money) * 1.05 #money是str,用int类型转换 | |
#判断用户金额是否足够 | |
if balance >= momey2: | |
#2)修改用户字典中的金额 | |
balance -= momey2 | |
user_dic['balance'] = balance | |
#记录流水 | |
flow = f'用户{username} 提现金额{money}成功,手续费是:{momey2 - float(money)}$ 剩余{balance}' | |
user_dic['flow'].append(flow) | |
#3)再保存数据,或更新数据 | |
db_handler.save(user_dic) | |
# money是str,用int类型转换 | |
return True, flow | |
def repay_interface(username, money): | |
''' | |
1.获取用户的金额 | |
2.给用户加钱操作 | |
:param username: | |
:param money: | |
:return: | |
''' | |
#1.获取用户字典 | |
user_dic = db_handler.select(username) | |
#2.直接做加钱的操作 | |
user_dic['balance'] += money | |
#记录流水 | |
flow = f'用户{username} 还款{money}成功! 当前额度为{user_dic["balance"]}' | |
user_dic['flow'].append(flow) | |
#3.调用数据处理层,将修改后的数据进行更新 | |
db_handler.save(user_dic) | |
return True, flow | |
def transfer_interface(login_user, to_user, money): | |
''' | |
1.获取'当前用户' 数据 | |
2.获取'目标用户' 数据 | |
3.获取转账金额 | |
:return: | |
''' | |
login_user_dic = db_handler.select(login_user) | |
to_user_dic = db_handler.select(to_user) | |
if not to_user_dic: | |
return False, '目标用户不存在' | |
#4)若用户存在,则判断'当前用户的转账金额' 是足够的 | |
if login_user_dic['balance'] >= money: | |
login_user_dic['balance'] -= money | |
to_user_dic['balance'] += money | |
#当前用户流水 | |
login_user_flow = f'用户{login_user} 给用户 {to_user} 转账 {money}$ 成功' | |
login_user_dic['balance'].append(login_user_flow) | |
#目标用户流水 | |
to_user_flow = f'用户{to_user} 给用户 {login_user} 转账 {money}$ 成功' | |
to_user_dic['flow'].append(to_user_flow) | |
#调用数据处理层,保存数据 | |
db_handler.save(login_user_dic) | |
db_handler.save(to_user_dic) | |
return True, login_user_flow | |
return False, '当前用户转账金额不足' | |
def check_flow_interface(login_user): | |
user_dic = db_handler.select(login_user) | |
return user_dic.get('flow') | |
#支付接口 | |
def pay_interface(login_user, cost): | |
user_dic = db_handler.select(login_user) | |
#判断用户金额 | |
if user_dic.get('balance') >= cost: | |
user_dic['balance'] -= cost | |
flow = f'用户消费金额:{cost}$' | |
user_dic['flow'].append(flow) | |
#保存数据 | |
db_handler.save(user_dic) | |
return True | |
return False |
-admin_interface.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/04 12:39 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: admin_interface.py | |
''' | |
from db import db_handler | |
from lib import common | |
admin_logger = common.get_logger('admin') | |
#修改额度接口 | |
def change_balance_interface(username, money): | |
user_dic = db_handler.select(username) | |
if user_dic: | |
#修改额度 | |
user_dic['balance'] = int(money) | |
db_handler.save(user_dic) | |
msg = f'管理员修改用户:{username}额度修改成功' | |
admin_logger.info(msg) | |
return True, '额度修改成功!' | |
return False, '修改额度用户不存在' | |
#冻结账户接口 | |
def lock_user_interface(username): | |
user_dic = db_handler.select(username) | |
if user_dic: | |
user_dic['locked'] = True | |
db_handler.save(user_dic) | |
return True, f'用户{username}冻结成功' | |
return False, '冻结用户不存在' |
5.db
-db_handler.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:57 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: db_handler.py | |
''' | |
''' | |
数据处理层 | |
-专门用户处理数据 | |
''' | |
import json | |
import os | |
from conf import settings | |
#查看数据 | |
def select(username): | |
#1)接收接口层传过来的username用户名,拼接用户json文件路劲 | |
user_path = os.path.abspath(os.path.join(settings.USER_DATA_PATH, f'{username}.json')).replace('\\', '/') | |
#2)校验用户json文件是否存在 | |
if os.path.exists(user_path): | |
#3)打开数据,并返回给接口层 | |
with open(user_path, 'r', encoding='utf-8') as f: | |
user_dic = json.load(f) # 导出数据 | |
return user_dic | |
#3)不return,默认返回return None | |
#保存数据 | |
def save(user_dic): | |
#1)拼接用户的数据字典 | |
username = user_dic.get('username') | |
user_path = os.path.abspath(os.path.join(settings.USER_DATA_PATH, f'{username}.json')).replace('\\', '/') | |
#2)保存用户数据 | |
with open(user_path, 'w', encoding='utf-8') as f: | |
# 导入数据(ensure_ascii=False,让文件中的中文数据显示更美观) | |
json.dump(user_dic, f, ensure_ascii=False) |
6.lib
-common.py
# -*- coding: utf-8 -*- | |
''' | |
@Time : 2022/09/02 14:50 | |
@Author : Rice | |
@CSDN : C_小米同学 | |
@FileName: common.py | |
''' | |
''' | |
存放公共方法 | |
''' | |
import hashlib | |
import logging.config | |
from conf import settings | |
def get_pwd_md5(password): | |
md5_obj = hashlib.md5() | |
md5_obj.update(password.encode('utf-8')) #传入的数据需要时"字节串" | |
salt = 'rice这是一个ATM' | |
md5_obj.update(salt.encode('utf-8')) | |
return md5_obj.hexdigest() | |
#登录认证装饰器 | |
def login_auth(func): | |
from core import src | |
def inner(*args, **kwargs): | |
if src.login_user: | |
res = func(* args, ** kwargs) | |
return res | |
else: | |
print('使用功能前,请先登录') | |
src.login() | |
return inner | |
#添加日子功能:(日志功能在接口层使用) | |
#获取日志功能 | |
#获取日志对象 | |
def get_logger(log_type): | |
''' | |
:param log_type: 比如是user日子,bank日子,购物商城日志 | |
:return: | |
''' | |
#1、加载日志配置信息 | |
logging.config.dictConfig(settings.LOGGING_DIC) | |
#2、获取日志对象 | |
logger = logging.getLogger(log_type) | |
return logger |
7.readme
项目说明书 | |
# 项目:ATM + 购物车 | |
# 项目需求 | |
模拟实现一个ATM + 购物商城程序 | |
1.额度 15000或自定义 ->注册功能 | |
2.实现购物商城,买东西加入 购物车,调用信用卡接口结账-》购物、支付 | |
3.可以提现,手续费5%-》提现功能 | |
4.支持多账户登录-》登录功能 | |
5.支持账户间转账 -》转账功能 | |
6.记录日常消费流水-》记录流水功能 | |
7.提供还款接口 -》还款功能 | |
8.ATM记录操作日志 —》记录日志功能 | |
9.提供管理接口,包括添加账户、用户额度,冻结账户等。。。-》管理员功能 | |
10.用户认证用装饰器-》登录认证装饰器 | |
## "用户视图层"展示给用户选择的功能 | |
1.注册功能 | |
2.登录功能 | |
3.查看余额 | |
4.提现功能 | |
5.还款功能 | |
6.转账功能 | |
7.查看流水 | |
8.购物功能 | |
9.查看购物车 | |
10.管理员功能 | |
# 一个项目如何从无到有 | |
# 一 需求分析 | |
1.拿到项目,想在客户那里讨论需求 | |
商量项目的功能能否实现,周期,价格,得到需求文档 | |
2.最后在公司内部需要开一次会议,得到最终的开发文档, | |
交给不同的岗位的程序员进行开发 | |
-Python:后端,爬虫 | |
-不同的岗位: | |
-UI界面设计: | |
-设计软件的布局,会根据软件的外观切成一张张图片 | |
-前端: | |
-拿到UI交给他的图片,去搭建网页页面 | |
-设计一些页面中,哪些位置需要接收数据,需要进行数据交互 | |
-后端: | |
-直接核心的业务逻辑,调度数据库进行数据的增删 | |
-测试: | |
-会给代码进行全面测试,比如压力测试,界面测试 | |
-运维 | |
-部署项目 | |
# 二 程序的架构设计 | |
## 1、程序设计的好处 | |
1)思路不清晰 | |
2)不会出现写一半推翻重写 | |
3)方便自己或以后的同时更好维护 | |
## 2、 三层架构设计的好处 | |
1)每个功能都分成三部分 | |
2)如果用户更换不同的用户界面或不同的数据储存机制,这样 | |
都不会影响接口层的核心逻辑代码。拓展性强 | |
3)可以在接口层,准确的记录接口和流水 | |
## 3、三层架构 | |
### 一 用户视图层 | |
用于与用户交互的,可以接受用户输入,打印接口返回的数据 | |
### 二 逻辑接口层 | |
接受 用户视图层 传递过来的参数,根据逻辑判断调用数据层加以处理, | |
并返回一个结果给用户视图层 | |
### 三 数据处理层 | |
接受接口层传递过来的参数,做数据的 | |
- 保存 save() | |
- 查看数据 select() | |
- 更新数据 | |
- 删除数据 | |
# 三 分任务开发 | |
# 四 测试 | |
# 五 上线 | |
# 统计代码 |