python購物車升級版

  • 2019 年 10 月 7 日
  • 筆記

各文件內容

前言

功能架構等請參考前一篇博客,此篇博客為進階版的存代碼展示。

詳細文件內容

啟動文件

starts.py啟動文件

import os  import sys    BASE_DIR = os.path.dirname(os.path.dirname(__file__))  sys.path.append(BASE_DIR)      from core import src  if __name__ == '__main__':      src.run()

配置文件

logging_dict.py日誌配置字典

import os  # ************************************   日誌配置字典   **************************************************  '''      --------------------------------------------      ------------* 需要自定義的配置 *-------------      --------------------------------------------  '''  # 定義三種日誌輸出格式 開始  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'  # 定義日誌輸出格式 結束      # 定義日誌文件的存放目錄與文件名(一般視情況選擇下面的兩個即可)  logfile_dir = os.path.dirname(os.path.dirname(__file__))  # log文件的目錄 (執行文件starts.py 在bin目錄下)  # logfile_dir = os.path.abspath(__file__)  # log文件的目錄 (執行文件starts.py 在項目根目錄下)  # 拼上 log 文件夾  logfile_dir = os.path.join(logfile_dir, 'log')  logfile_name = 'ATM_Shop_Cart.log'  # log文件名    # 如果不存在定義的日誌目錄就創建一個  if not os.path.isdir(logfile_dir):      os.mkdir(logfile_dir)    # log文件的全路徑  logfile_path = os.path.join(logfile_dir, logfile_name)    # 像日誌文件的最大限度、個數限制,日誌過濾等級等也可以在下面的對應地方限制    '''      --------------------------------------------      --------------* log配置字典 *---------------      --------------------------------------------  '''  # 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,超過5M就會換一個日誌文件繼續記錄              'backupCount': 5,  # 日誌文件的數量上限 5個,超出會把最早的刪除掉再新建記錄日誌              'encoding': 'utf-8',  # 日誌文件的編碼,再也不用擔心中文log亂碼了          },      },      'loggers': {          # logging.getLogger(__name__)拿到的logger配置          '': {              'handlers': ['default', 'console'],  # 這裡把上面定義的兩個handler都加上,即log數據既寫入文件又打印到屏幕              # 'handlers': ['default'],  # ------------- 正式上線的時候改成這個,取消控制台打印,節省資源  -------------              'level': 'DEBUG',              'propagate': True,  # 向上(更高level的logger)傳遞          },      },  }

settings.py配置文件

import os  import sys  BASE_DIR = os.path.dirname(os.path.dirname(__file__))  sys.path.append(BASE_DIR)

入口文件

src.py入口文件

from interface import user_interface  from lib import common  from interface import bank_interface  from interface import shop_interface      def register():      while True:          username = input("請輸入用戶名>>>:").strip()          if username == 'q':              return False          if user_interface.check_user_exits(username):              print("該用戶已存在,請換一個試試!")              continue          pwd = input("請輸入密碼>>>:").strip()          if pwd == 'q':              return False          repwd = input("請再次輸入密碼>>>:").strip()          if pwd == 'q':              return False          if repwd != pwd:              print("兩次密碼不一致,請您重新輸入!")              continue          flag = user_interface.register(username, pwd)          if not flag:              print("註冊失敗,請重試!")              continue          else:              print(f"{username}註冊成功~")              return True      def login():      while True:          username = input("請輸入用戶名>>>:").strip()          if username == 'q':              return False          if not user_interface.check_user_exits(username):              print("該用戶不存在,請檢查輸入!")              continue          pwd = input("請輸入密碼>>>:").strip()          if pwd == 'q':              return False          flag = user_interface.login(username, pwd)          if not flag:              print("您的密碼有誤或賬戶已被凍結,請重新登錄!")              continue          else:              print(f"登陸成功,{username}您好~")              return True      @common.login_auth  def logout():      user_interface.logout()      print("歡迎下次登錄,祝您生活愉快~")      @common.login_auth  def check_balance():      username = current_user.get("username")      balance = user_interface.check_balance(username)      print(f"{username}您好,您的賬戶餘額為{balance}。")      @common.login_auth  def check_flow():      username = current_user.get('username')      flow = user_interface.check_flow(username)      if flow:          print(f"{username}您好,您的流水如下:")          for line in flow:              print(line)      else:          print(f"{username}您好,您的賬戶暫無流水記錄~")      # ---------------------  # 銀行接口  @common.login_auth  def repay():      username = current_user.get('username')      while True:          money = input('請輸入您的還款金額>>>:').strip()          if money == 'q':              return False          elif not money.isdigit():              print("請正確輸入金額")              continue          else:              money = int(money)              bank_interface.repay(username, money)              print("還款成功!")              return True      @common.login_auth  def withdraw():      username = current_user.get('username')      while True:          money = input('請輸入您的提現金額>>>:').strip()          if money == 'q':              return False          elif not money.isdigit():              print("請正確輸入金額")              continue          else:              money = int(money)              flag = bank_interface.withdraw(username, money)              if flag:                  print("提現成功!")                  return True              else:                  print("您的餘額不足提現金額(提現需包含0.05%的手續費)。")      @common.login_auth  def transfer():      username = current_user.get('username')      while True:          target_user = input("請輸入您的轉賬目標用戶>>>:").strip()          if user_interface.check_user_exits(target_user):              money = input('請輸入您的轉賬金額>>>:').strip()              if money == 'q':                  return False              elif not money.isdigit():                  print("請正確輸入金額")                  continue              else:                  money = int(money)                  flag = bank_interface.transfer(username, target_user, money)                  if not flag:                      print("轉賬失敗,請確認您的餘額是否充足!")                      continue                  print("轉賬成功!")                  return True          print(f"{target_user}用戶不存在,請您重新輸入!")      # ---------------------  # 購物功能  @common.login_auth  def shop():      username = current_user['username']      while True:          print("------------- 商品列表 -------------")          for key in shopping_list:              print(f"{key}.{shopping_list.get(key)[0]} {shopping_list.get(key)[1]}")          choice = input("請輸入商品編號>>>:").strip()          if choice == 'q':              return False          elif choice in shopping_list:              # 開始購物              is_buy = input("請選擇購買或加入購物車(y購買/n加入購物車)(q退出)").strip()              if is_buy == 'q':                  return False              good = shopping_list[choice][0]              price = shopping_list[choice][1]                if is_buy == 'y':                  flag = shop_interface.pay_good(username, good, price)                  if not flag:                      print(f"您的餘額不足以購買該商品,請換一個試試")                  else:                      print(f"{good}商品購買成功!")              elif is_buy == 'n':                  # 加入購物車                  flag = shop_interface.put_shop_cart(username, good, price)                  if not flag:                      print(f"{good}該商品已在購物車中啦~")                  else:                      print(f"{good}成功放入購物車")                  pass              else:                  print("請正確輸入!")                  continue          else:              print("請輸入正確的商品編號!")              continue      @common.login_auth  def check_shop_cart():      username = current_user['username']      shop_cart = shop_interface.get_shop_cart(username)      if shop_cart:          print(f"{username}您好,您的購物車商品列表如下")          for shop, price in shop_cart.items():              print(shop, price)      else:          print(f"您的購物車裡還沒有東西哦~")      # ---------------------  # 管理員功能  @common.login_auth  @common.admin_auth  def lock_user():      username = current_user['username']      while True:          target_user = input("請輸入您要凍結的目標用戶>>>:").strip()          if user_interface.check_user_exits(target_user):              user_interface.lock_user(username, target_user)              print(f"{target_user}用戶已凍結。")              return True          print(f"{target_user}用戶不存在,請您重新輸入!")      @common.login_auth  @common.admin_auth  def unlock_user():      username = current_user['username']      while True:          target_user = input("請輸入您要解凍的目標用戶>>>:").strip()          if user_interface.check_user_exits(target_user):              user_interface.unlock_user(username, target_user)              print(f"{target_user}用戶已成功解凍。")              return True          print(f"{target_user}用戶不存在,請您重新輸入!")      @common.login_auth  @common.admin_auth  def change_balance():      username = current_user['username']      while True:          target_user = input("請輸入您要更改的目標用戶>>>:").strip()          if user_interface.check_user_exits(target_user):              money = input('請輸入金額>>>:').strip()              if money == 'q':                  return False              elif not money.isdigit():                  print("請正確輸入金額")                  continue              else:                  money = int(money)                  flag = user_interface.change_balance(username, target_user, money)                  if not flag:                      print("不能設置自己的餘額,請換個用戶試試。")                      continue                  print(f"{target_user}用戶餘額成功修改為{money}元。")                  return True          print(f"{target_user}用戶不存在,請您重新輸入!")      func_list = {      '1': register,      '2': login,      '3': logout,      '4': check_balance,      '5': check_flow,      '6': repay,      '7': withdraw,      '8': transfer,      '9': shop,      '10': check_shop_cart,      '11': lock_user,      '12': unlock_user,      '13': change_balance,  }      current_user = {      'username': '',      'pwd': None,      'balance': 0,      'lock': False,      'flow': [],      'shop_cart': {},      'is_admin': False  }      shopping_list = {      "1": ['廣東鳳爪', 10],      "2": ['麵疙瘩', 15],      "3": ['mac', 12888],      "4": ['tesla', 1222222]  }      def run():      while True:          print("""------------------------------------------------------------------          1.註冊        2.登錄        3.註銷        4.查看餘額          5.查看流水    6.還款        7.提現        8.轉賬          9.購物        10.查看購物車  11.鎖定用戶   12.解鎖用戶          13.更改用戶餘額                11-13為管理員功能哦,只有管理員才能操作!          ------------------------------------------------------------------""")          choice = input("請選擇功能編號>>>:").strip()          if choice == 'q':              print("感謝您的使用,歡迎下次再來~")              return False          elif choice in func_list:              func_list[choice]()          else:              print("您的輸入有誤,請重新輸入")

數據處理層

db_handler.py數據處理文件

import os  import json  BASE_DIR = os.path.dirname(os.path.dirname(__file__))  DB_DIR = os.path.join(BASE_DIR, 'db')      def select(username: str):      user_dir = os.path.join(DB_DIR, f"{username}.json")      if not os.path.exists(user_dir):          return False      else:          with open(user_dir, mode='r', encoding='utf-8') as f:              user_dict = json.load(f)              return user_dict      def save(user_dict: dict):      user_dir = os.path.join(DB_DIR, f"{user_dict['username']}.json")      with open(user_dir, mode='w', encoding='utf-8') as f:          json.dump(user_dict, f, ensure_ascii=False)      return True

用戶數據信息

db/swb.json用戶信息文件1

{"username": "swb", "pwd": "59f471f262ab586fb959ded0e2c7b94f", "balance": 10, "lock": false, "flow": ["swb購買了廣東鳳爪,花費10元,現餘額為14990元", "swb購買了麵疙瘩,花費15元,現餘額為14975元", "管理員tank將您的賬戶餘額重置為10元。"], "shop_cart": {"廣東鳳爪": 10, "麵疙瘩": 15, "mac": 12888, "tesla": 1222222}, "is_admin": false}

db/tank.json用戶信息文件2

{"username": "tank", "pwd": "59f471f262ab586fb959ded0e2c7b94f", "balance": 14975, "lock": false, "flow": ["tank購買了廣東鳳爪,花費10元,現餘額為14990元", "tank購買了麵疙瘩,花費15元,現餘額為14975元"], "shop_cart": {"tesla": 1222222}, "is_admin": true}

接口層

interface/bank_interface.py銀行功能接口文件

from db import db_handler  from lib import common  logger = common.get_logger('bank_interface')      def repay(username: str, money: float):      user_dict = db_handler.select(username)      user_dict['balance'] += money      user_dict['flow'].append(f"{username}還款{money}元,現餘額為{user_dict['balance']}。")      db_handler.save(user_dict)      logger.info(f"{username}還款{money}元,現餘額為{user_dict['balance']}。")      return True      def withdraw(username: str, money: float):      user_dict = db_handler.select(username)      if money*1.05 > user_dict['balance']:          return False      else:          user_dict['balance'] -= money*1.05      user_dict['flow'].append(f"{username}提現{money}元,手續費{money*0.05}元,現餘額為{user_dict['balance']}元")      db_handler.save(user_dict)      logger.info(f"{username}提現{money}元,手續費{money*0.05}元,現餘額為{user_dict['balance']}元")      return True      def transfer(username: str, target_username: str, money: float):      user_dict = db_handler.select(username)      if user_dict['balance'] < money:          return False      user_dict['balance'] -= money      user_dict['flow'].append(f"{username}向{target_username}轉賬{money}元。")      db_handler.save(user_dict)        target_user_dict = db_handler.select(target_username)      target_user_dict['balance'] += money      target_user_dict['flow'].append(f"{target_username}收到{username}轉賬{money}元。")      db_handler.save(target_user_dict)        logger.info(f"{username}向{target_username}轉賬{money}元。")      return True

interface/shop_interface.py購物車功能接口文件

from db import db_handler  from lib import common  logger = common.get_logger('shop')      def get_shop_cart(username: str):      user_dict = db_handler.select(username)      return user_dict['shop_cart']      def put_shop_cart(username: str, good: str, price: float):      user_dict = db_handler.select(username)      shop_cart = user_dict['shop_cart']      if good in shop_cart:          return False      else:          shop_cart[good] = price      user_dict['shop_cart'] = shop_cart      db_handler.save(user_dict)      logger.info(f"商品{good},單價{price},已加入{username}的購物車~")      return True      def pay_good(username, good, price):      user_dict = db_handler.select(username)      if user_dict['balance'] <= price:          return False      else:          user_dict['balance'] -= price          user_dict['flow'].append(f"{username}購買了{good},花費{price}元,現餘額為{user_dict['balance']}元")          db_handler.save(user_dict)          logger.info(f"{username}購買了{good},花費{price}元,現餘額為{user_dict['balance']}元")          return True

interface/user_interface.py用戶功能接口文件

from db import db_handler  from lib import common  logger = common.get_logger('user_interface')      def check_user_exits(username: str):      flag = db_handler.select(username)      if not flag:          return False      return True      def register(username: str, pwd: str, balance=15000):      pwd = common.get_md5(pwd)      user_dict = {          'username': username,          'pwd': pwd,          'balance': balance,          'lock': False,          'flow': [],          'shop_cart': {},          'is_admin': False      }      db_handler.save(user_dict)      logger.info(f"{username}用戶註冊成功,初始餘額為{balance}元。")      return True      def login(username: str, pwd: str):      pwd = common.get_md5(pwd)      user_dict = db_handler.select(username)      if user_dict['pwd'] == pwd and not user_dict['lock']:          from core import src          src.current_user = user_dict          return True      else:          return False      def logout():      from core import src      logger.info(f"{src.current_user['username']}用戶註銷登錄。")      src.current_user = {          'username': None,          'pwd': None,          'balance': None,          'lock': False,          'flow': [],          'shop_cart': {},          'is_admin': False      }      return True      def check_balance(username: str):      user_dict = db_handler.select(username)      return user_dict['balance']      def check_flow(username: str):      user_dict = db_handler.select(username)      return user_dict['flow']      def lock_user(username: str, target_user: str):      target_user_dict = db_handler.select(target_user)      target_user_dict['lock'] = True      db_handler.save(target_user_dict)      logger.info(f"{username}將{target_user}賬戶凍結。")      return True      def unlock_user(username: str, target_user: str):      target_user_dict = db_handler.select(target_user)      target_user_dict['lock'] = False      db_handler.save(target_user_dict)      logger.info(f"{username}將{target_user}賬戶解凍。")      return True      def change_balance(username: str, target_user: str, money: float):      if username == target_user:          return False      target_user_dict = db_handler.select(target_user)      target_user_dict['balance'] = money      target_user_dict['flow'].append(f"管理員{username}將您的賬戶餘額重置為{money}元。")      db_handler.save(target_user_dict)      logger.info(f"{username}將{target_user}的賬戶餘額改為{money}元。")      return True      # 這些管理員方法用裝飾器判斷他是不是管理員

通用方法

lib/common.py通用方法文件

import logging.config  from conf import logging_dict  import hashlib      # 日誌字典使用  def get_logger(type_name: str):      logging.config.dictConfig(logging_dict.LOGGING_DIC)      logger = logging.getLogger(type_name)      return logger      # 登錄裝飾器  def login_auth(func):      def inner(*args, **kwargs):          from core import src          if src.current_user.get('username'):              # 登錄驗證              res = func(*args, **kwargs)              return res          else:              print("請登錄後再操作!")              src.login()      return inner      # 管理員驗證  def admin_auth(func):      def inner(*args, **kwargs):          from core import src          if src.current_user.get('is_admin'):              # 判斷是不是管理員              res = func(*args, **kwargs)              return res          else:              print("您不是管理員,不能使用此功能哦~")      return inner      # md5值獲取  def get_md5(string: str) -> str:      md5 = hashlib.md5()      md5.update('md5_salt'.encode('utf-8'))      md5.update(string.encode('utf-8'))      return md5.hexdigest()      if __name__ == '__main__':      logger = get_logger('common')      logger.info('info測試數據啦~')      logger.debug('debug測試數據啦~')

日誌記錄

log/ATM_Shop_Cart.log日誌記錄文件

[2019-07-23 21:55:50,172][MainThread:2688][task_id:user_interface][user_interface.py:25][INFO][swb用戶註冊成功,初始餘額為15000元。]  [2019-07-23 21:56:07,970][MainThread:2688][task_id:shop][shop_interface.py:30][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元]  [2019-07-23 21:56:11,611][MainThread:2688][task_id:shop][shop_interface.py:19][INFO][商品麵疙瘩,單價15,已加入swb的購物車~]  [2019-07-23 21:56:13,812][MainThread:2688][task_id:shop][shop_interface.py:19][INFO][商品mac,單價12888,已加入swb的購物車~]  [2019-07-23 21:56:54,035][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品廣東鳳爪,單價10,已加入swb的購物車~]  [2019-07-23 21:56:55,516][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品麵疙瘩,單價15,已加入swb的購物車~]  [2019-07-23 21:56:56,882][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品mac,單價12888,已加入swb的購物車~]  [2019-07-23 21:56:58,797][MainThread:764][task_id:shop][shop_interface.py:20][INFO][商品tesla,單價1222222,已加入swb的購物車~]  [2019-07-23 21:57:06,937][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元]  [2019-07-23 21:57:09,363][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了麵疙瘩,花費15元,現餘額為14985元]  [2019-07-23 21:57:10,666][MainThread:764][task_id:shop][shop_interface.py:31][INFO][swb購買了mac,花費12888元,現餘額為2112元]  [2019-07-23 21:59:27,610][MainThread:14372][task_id:shop][shop_interface.py:31][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元]  [2019-07-23 22:00:37,898][MainThread:7112][task_id:shop][shop_interface.py:32][INFO][swb購買了廣東鳳爪,花費10元,現餘額為14990元]  [2019-07-23 22:00:39,419][MainThread:7112][task_id:shop][shop_interface.py:32][INFO][swb購買了麵疙瘩,花費15元,現餘額為14975元]  [2019-07-23 22:01:08,585][MainThread:1056][task_id:user_interface][user_interface.py:25][INFO][tank用戶註冊成功,初始餘額為15000元。]  [2019-07-23 22:01:18,705][MainThread:1056][task_id:shop][shop_interface.py:32][INFO][tank購買了廣東鳳爪,花費10元,現餘額為14990元]  [2019-07-23 22:01:23,370][MainThread:1056][task_id:shop][shop_interface.py:32][INFO][tank購買了麵疙瘩,花費15元,現餘額為14975元]  [2019-07-23 22:01:29,289][MainThread:1056][task_id:shop][shop_interface.py:20][INFO][商品tesla,單價1222222,已加入tank的購物車~]  [2019-07-23 22:03:05,065][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。]  [2019-07-23 22:03:18,514][MainThread:1056][task_id:user_interface][user_interface.py:69][INFO][tank將swb賬戶凍結。]  [2019-07-23 22:03:20,986][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。]  [2019-07-23 22:03:45,178][MainThread:1056][task_id:user_interface][user_interface.py:77][INFO][tank將swb賬戶解凍。]  [2019-07-23 22:04:05,704][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][swb用戶註銷登錄。]  [2019-07-23 22:04:18,321][MainThread:1056][task_id:user_interface][user_interface.py:88][INFO][tank將swb的賬戶餘額改為10元。]  [2019-07-23 22:04:22,425][MainThread:1056][task_id:user_interface][user_interface.py:42][INFO][tank用戶註銷登錄。]

注意: # swb 用戶為管理員用戶,可以執行管理員操作(swb 以及 tank的密碼均為 123),右鍵starts.py文件運行即可