经过一段时间学习,掌握了不少python基础,今天要写的项目是登录注册购物三种功能的小项目。(由于结构简单并没有上传git)
包 | 功能 |
---|---|
core | 注册、登录、购物核心功能 |
data | 存放注册的用户数据、商品信息 |
public | 存放编写的方法文件 |
log | 存放日志文件 |
config | 存放配置文件 |
没有写版本的对应是python3.7的
开发环境 | 版本 |
---|---|
python | 3.7 |
json | |
sys | |
os | |
time | |
hashlib | |
logging | |
re |
对于核心功能首先是注册需要注意以下几点:
其中registerM为用户界面函数相当于前端
而regUser便是业务逻辑层代码
后期可以将界面函数转移替换成对应的前端接口
from public.tools import *
from data.db_func import *
def registerM():
print("用户注册")
username = input("请输入用户名:").strip()
password1 = input("请输入密码(密码开头必须是字母长度6到18位,可以使数字字母下划线):").strip()
password2 = input("请再次输入密码:").strip()
is_superuser = input("请输入邀请码(可不输入,输入后可注册为管理员)邀请码(hao123):").strip()
regUser(username, password1, password2, is_superuser, "注册")
def regUser(username, password1, password2, is_superuser, str):
# 获取所有用户
users = get_users()
is_superuser1 = False
# 先比对是否存在该用户名
file = chain_file(two_last_file(), "data", "user.txt")
usernames = get_username(read_txt(file))
if username in usernames:
print("该用户名已被注册")
return
else:
# 俩次密码是否一致,是否符合密码设置规则,是否以大小写字母开头包含字母数字下划线且6~18位组合
if password1 == password2:
if rightful_password(password1) != None:
# 根据用户权限设置密码加密方式
if is_superuser == "hao123":
is_superuser1 = True
password3 = encrypt_salt_md5(password1)
else:
is_superuser1 = False
password3 = encrypt_md5(password1)
user = {"username":username, "password":password3, "money": 0, "is_superuser":is_superuser1, "is_shd":False, "shop_car":{}}
users.append(user)
write_txt(USER_FILE,users)
print("%s成功,2秒后将返回主界面"%str)
time.sleep(2)
else:
print("密码不符合规定")
registerM()
else:
print("俩次密码不一致")
registerM()
if __name__ == '__main__':
registerM()
登录模块注意以下几点:
其中loginM为用户界面函数相当于前端
而login便是业务逻辑层代码
后期可以将界面函数转移替换成对应的前端接口
from public.tools import *
from data.db_func import *
def loginM():
print("登录")
username = input("请输入用户名:")
password = input("请输入密码:")
login(username, password)
def login(username, password):
# 读取对应用户密码及其权限
password1 = get_user_password(username)
is_superuser = get_user_isSuperuser(username)
# 判断用户是否被拉黑
users = get_users()
for u in users:
if u["username"] == username:
if u["is_shd"]:
print("用户已被拉黑无法登陆")
time.sleep(2)
return
# 判断是否存在该用户
# 先比对是否存在该用户名
file = chain_file(two_last_file(), "data", "user.txt")
usernames = get_username(read_txt(file))
if username in usernames:
# 先判断用户权限类型再判断用户输入的密码和已有密码是否一致
if is_superuser:
if password1 == encrypt_salt_md5(password):
add_cookie(username, is_superuser)
print("登陆成功")
else:
print("密码或用户名错误")
loginM()
else:
if password1 == encrypt_md5(password):
add_cookie(username, is_superuser)
print("登陆成功")
else:
print("密码或用户名错误")
loginM()
else:
print("密码或用户名错误")
loginM()
if __name__ == '__main__':
loginM()
购物模块注意以下几点:
from public.tools import *
from data.db_func import *
@user_is_login
def shopM():
print("购物界面")
print("1.购买商品")
print("2.结算购物车")
print("0.返回主界面")
key1 = input("请选择需要的功能:").strip()
commoditys = load_commdity()
users = get_users()
username = COOKIE["user"]["username"]
if key1.isdigit() and re.search("[0-2]?",key1):
key = int(key1)
if key == 1:
add_shop(commoditys, users, username)
shopM()
elif key == 2:
settle_shop(users, username)
shopM()
else:
print("返回主界面")
else:
print("请输入正确的功能序号")
shopM()
def add_shop(commoditys, users, username):
for u in users:
if u["username"] == username:
u["shop_car"]
show_conndity()
commodity_name = input("请输入需要的商品:")
price = commoditys[commoditys.index(commodity_name) + 1]
if commodity_name in commoditys:
sc1 = input("请输入购买的数量:")
if is_sum(sc1):
num = int(sc1)
if commodity_name in u["shop_car"]:
if num > 0:
u["shop_car"][commodity_name][0] += num # 添加或减少到购物车操作
print("购物车:", u["shop_car"])
write_txt(USER_FILE,users)
time.sleep(2)
elif u["shop_car"][commodity_name][0] + num > 0:
u["shop_car"][commodity_name][0] = u["shop_car"][commodity_name][0] + num
print("购物车:", u["shop_car"])
write_txt(USER_FILE,users)
time.sleep(2)
elif u["shop_car"][commodity_name][0] + num == 0:
del u["shop_car"][commodity_name]
print("购物车:",u["shop_car"])
write_txt(USER_FILE,users)
time.sleep(2)
else:
print("购物车中数量不足或不存在,无法减少该商品数量")
else:
u["shop_car"][commodity_name] = [num, price]
write_txt(USER_FILE,users)
time.sleep(2)
else:
print("购买数量必须为整数")
else:
print("不能购买不存在的商品")
def settle_shop(users, username): #结算购物车
for u in users:
if u["username"] == username:
shop_list = u["shop_car"]
user_money = u["money"]
if len(shop_list) == 0:
print("你还没有购物快去购物一番吧")
else:
shop_list_value = shop_list.values()
sum = 0
for i in shop_list_value:
sum += int(i[0]) * int(i[1])
if u["money"] >= sum:
u["money"] -= sum
u["shop_car"].clear()
print("本次你消费了%d¥,账户余额:%d¥,欢迎下次再来" %(sum, u["money"]))
write_log("消费", "%s用户消费%d元"%(username, sum))
write_txt(USER_FILE, users)
else:
print("你的余额不足,请尽快充值")
# 获取商品信息
def load_commdity():
file = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "commodity.txt")
with open(file, "r", encoding="utf8") as c:
commditys = json.loads(c.read())
return commditys
# 展示商品
def show_conndity():
commoditys = load_commdity()
k = 0
for i in commoditys:
if k % 2 == 0:
print("商品:", i)
else:
print("单价:", i)
k += 1
用户模块注意以下几点:
from public.tools import *
from core.register import regUser
from data.db_func import *
import re
@user_is_login
def userM():
print("用户界面")
username = COOKIE["user"]["username"]
is_superuser = COOKIE["user"]["is_superuser"]
user_func(is_superuser)
key1 = input("请选择功能:").strip()
if key1.isdigit() and re.search("[0-8]?",key1):
key = int(key1)
if key == 1:
select_money(username)
userM()
elif key == 2:
charge(username)
userM()
elif key == 3:
get_card(username)
userM()
elif key == 4:
give_money(username)
userM()
elif key == 5:
select_expense(username)
userM()
elif key == 6:
forbid_user()
userM()
elif key == 7:
del_user()
userM()
elif key == 8:
add_user()
userM()
else:
print("返回主界面")
else:
print("请输入正确的功能序号")
userM()
# 用户功能模块
def user_func(is_superuser):
func = ["余额查询", "充值", "提现", "转账", "流水查看", "拉黑用户", "删除用户", "新增用户"]
if is_superuser:
for f, k in enumerate(func, start=1):
print("%d、%s"%(f, k))
print("0、返回")
else:
for f, k in enumerate(func, start=1):
if f != "拉黑用户":
print("%d、%s"%(f, k))
print("0、返回")
# 余额查询
def select_money(username):
print("用户:%s,余额:%d"%(username, get_user(username)["money"]))
# 充值
def charge(username):
print("充值界面")
select_money(username)
money = input("请输入充值金额(0起步整数充值):").strip()
users = get_users()
if money.isdigit():
for u in users:
if u["username"] == username:
u["money"] += int(money)
write_txt(USER_FILE,users)
print("充值成功")
select_money(username)
write_log("充值", "%s用户充值%d元" % (u["username"], int(money)))
time.sleep(2)
else:
print("充值金额请输入大于0的整数")
charge(username)
# 提现
def get_card(username):
print("提现界面")
select_money(username)
money = input("请输入提现金额(0起步整数充值):").strip()
users = get_users()
if money.isdigit():
for u in users:
if u["username"] == username:
if u["money"] >= int(money):
u["money"] -= int(money)
write_txt(USER_FILE, users)
print("提现成功")
select_money(username)
write_log("提现", "%s用户提现%d元" %(u["username"], u["money"]))
time.sleep(2)
else:
print("余额不足无法提现")
get_card(username)
else:
print("提现金额请输入大于0的整数")
get_card(username)
# 转账
def give_money(username):
print("转账界面")
select_money(username)
username1 = input("请输入转账对象用户名:").strip()
money = input("请输入提现金额(0起步整数充值):").strip()
users = get_users()
if money.isdigit():
for u in users:
if u["username"] == username:
if u["money"] >= int(money):
if username1 in get_username(users):
for u1 in users:
if u1["username"] == username1:
u1["money"] += int(money)
u["money"] -= int(money)
write_txt(USER_FILE, users)
print("转账成功")
write_log("转账", "%s用户向%s用户转账%d元" %(u["username"], u1["username"], int(money)))
select_money(username)
time.sleep(2)
else:
print("转账用户名错误")
give_money(username)
else:
print("你的余额不足,无法转账")
give_money(username)
else:
print("转账金额请输入大于0的整数")
get_card(username)
# 流水查看
def select_expense(username):
print("流水查看")
with open(LOGFILE_PATH, "r", encoding="utf8") as f:
data = f.read()
data1 = re.findall(username + "用户消费.*元", data)
data2 = []
for d in data1:
data2.append(re.findall("[0-9]+", d))
sum = 0
for k in data2:
sum += int(k[0])
print("%s用户共消费了%d元"%(username, sum))
# 拉黑用户
def forbid_user():
print("拉黑用户界面")
print("拉黑后的用户无法登陆")
users = get_users()
usernames = get_username(users)
print("系统中所有的用户:", usernames)
username = input("请输入需要拉黑的用户名").strip()
if username in usernames:
for u in users:
if u["username"] == username:
u["is_shd"] = True
write_txt(USER_FILE, users)
print("拉黑成功")
write_log("拉黑用户", "拉黑了%s用户"%username)
time.sleep(2)
else:
print("没有该用户")
forbid_user()
# 删除用户
def del_user():
print("删除用户界面")
users = get_users()
usernames = get_username(users)
print("系统中所有的用户:", usernames)
username = input("请输入需要删除的用户名:").strip()
if username in usernames:
i = 0
for u in users:
if u["username"] == username:
del users[i]
write_txt(USER_FILE, users)
print("删除成功")
write_log("删除用户", "删除了%s用户"%username)
time.sleep(2)
i += 1
else:
print("没有该用户")
forbid_user()
# 添加用户
def add_user():
users = get_users()
usernames = get_username(users)
print("系统中所有的用户:", usernames)
username = input("请输入需要添加的用户名").strip()
password = input("请输入需要添加的密码").strip()
is_superuser = input("请输入需要添加的用户是否为管理员(输入1为是,不输入为否)").strip()
if is_superuser == "1":
is_superuser = "hao123"
regUser(username, password, password, is_superuser, "添加")
write_log("添加用户", "添加了用户名:%s"%username)
users = get_users()
usernames = get_username(users)
print("系统中所有的用户:", usernames)
time.sleep(2)
if __name__ == '__main__':
select_expense("kdq")
该包用于存放用户数据文件和商品信息,以及对数据库操作的代码
from config.setting import *
from public.tools import write_txt, read_txt
# 不存在user.txt时自动生成user.txt文件
def auto_user():
open(USER_FILE, "w+")
data = []
write_txt(USER_FILE, data)
return read_txt(USER_FILE)
# 获取所有用户名
def get_username(data):
users = []
for u in data:
users.append(u["username"])
return users
# 获取所有用户数据
def get_users():
try:
return read_txt(USER_FILE)
except Exception:
return auto_user()
# 获取对应用户数据
def get_user(username):
try:
users = get_users()
for u in users:
if u["username"] == username:
return u
return []
except Exception:
return auto_user()
# 获取对应用户权限
def get_user_isSuperuser(username):
user = get_user(username)
if user:
return user["is_superuser"]
# 获取对应用户的密码
def get_user_password(username):
user = get_user(username)
if user:
return user["password"]
用户文本
{“username”:username, “password”:password, “money”:money, “is_superuser”:True, “is_shd”:True, “shop_car”:{“shop_name”:[num, price]} }
商品文本
[“梨子”,10, “苹果”,5, “只狗key”,198, “一只贝爷”,998, “水果手机”,6999, “蔡虚鲲”,114514]
该包用于存放一些方法,编写方法可以让文件可读性提高、降低不重要代码对核心算法的干扰
import json
import re
import hashlib
import time
import logging
import logging.config
from config.setting import *
# 获取执行文件上一级目录
def last_file():
return os.path.dirname(__file__)
# 获取执行文件上一级目录的根目录
def two_last_file():
return os.path.dirname(os.path.dirname(__file__))
# 拼接路径
def chain_file(*args, **kwargs):
return os.path.join(*args, **kwargs)
# 读取txt文件内容
def read_txt(file):
with open(file, "r", encoding="utf8") as f:
return json.loads(f.read())
# 保存txt文件
def write_txt(file, data):
with open(file, "w", encoding="utf8") as f:
f.write(json.dumps(data))
# 验证密码是否符合规则
def rightful_password(password):
condition = re.compile("^[a-zA-Z]\w{5,17}$")
return re.search(condition, password)
# md5加密
def encrypt_md5(password):
md5 = hashlib.md5()
md5.update(password.encode("utf8"))
return md5.hexdigest()
# md5加盐加密
def encrypt_salt_md5(password):
md5 = hashlib.md5("superuser".encode("utf8"))
md5.update(password.encode("utf8"))
return md5.hexdigest()
# 登录后记录cookie
def add_cookie(username, is_superuser):
COOKIE["user"] = {"username":username, "is_superuser":is_superuser}
# 不存在log文件夹时自动生成log文件夹
def auto_log():
file = os.path.join(os.path.dirname(os.path.dirname(__file__)), "log")
if not os.path.isdir(file):
os.makedirs(file)
# 记录日志
def write_log(func, content):
auto_log()
logging.config.dictConfig(LOGGING_DIC) # 自动加载字典中的配置
logger1 = logging.getLogger(func)
logger1.debug(content)
from core import login
# 是否登录装饰器
def user_is_login(func):
def inner(*args, **kwargs):
try:
if COOKIE["user"] != None:
res = func(*args, *kwargs)
return res
except Exception:
print("没有登陆,请先登录再操作")
print("2秒后跳转到登录界面界面")
time.sleep(2)
login.loginM()
return inner
# 判断输入是否为正数或负数
def is_sum(str):
try:
k = int(str)
return isinstance(k, int)
except ValueError:
return True
if __name__ == '__main__':
pass
包中的setting模块用于存放一些很少变动的固定内容,其中包含了用户数据文件路径、日志配置字典
import os
COOKIE = {}
USER_FILE = os.path.join(os.path.dirname(os.path.dirname(__file__)), "data", "user.txt")
# 自定义文件路径
LOGFILE_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), "log", "log.txt")
# 定义日志输出格式 开始
STANDARD_FORMAT = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \
'[%(levelname)s][%(message)s]'
# log配置字典
LOGGING_DIC = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'standard': {
'format': STANDARD_FORMAT
}
},
'filters': {}, # 过滤日志
'handlers': {
#打印到终端的日志
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler', # 打印到屏幕
'formatter': 'standard'
},
#打印到文件的日志,收集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)传递
}
},
}
start模块用于启动软件
import re
from core import login, register, shop, user
def startM():
print("主界面")
print("1.用户登录")
print("2.用户注册")
print("3.购物")
print("4.用户管理")
print("0.退出程序")
key1 = input("请选择功能:").strip()
if key1.isdigit() and re.search("[0-4]?",key1):
key = int(key1)
if key == 1:
login.loginM()
startM()
elif key == 2:
register.registerM()
startM()
elif key == 3:
shop.shopM()
startM()
elif key == 4:
user.userM()
startM()
else:
print("退出软件")
else:
print("输入错误")
startM()
if __name__ == '__main__':
startM()
目前项目划分比较合理,将整个项目分为了三个部分表现层、业务逻辑层、数据持久层,由于没有使用前端和数据库只能大致模拟这样的效果,项目分割后方便协作开发、产生异常时也不会项目影响。