python写出租车计费系统_基于Python的运动计费管理系统

动机

小伙伴们最近迷恋上羽毛球,组织了个小群,办了公用的运动卡用于开场,考虑不是每次活动都是全员参与,需要一个计费的系统来计算每个人需要交的费用。商讨后决定采用“预充-扣费”的方式,则需要一个系统进行计费和扣费。

技术路线规划

模块名

语言

备注

管理核心

Python

使用JSON存储信息

Web后端

Python

Flask框架

Web前端

HTML

Jinja框架渲染

实现

核心模块——用户状态管理

该部分是整个计费系统的核心,用于管理每个用户的余额。使用一个类表示用户,需要的属性为

状态列表(用户名,ID,使用次数,余额)

需要的方法有:

创建用户(创建新的JSON文件)

读取用户状态(从已有的JSON文件中)

扣费(使用次数增加1,余额减小)

充值(余额增加)

保存状态(将现有的状态写入JSON文件)

代码如下

# -*- coding: utf-8 -*-

import json

import os

class UserHanlde(object):

"""docstring for UserHanlde"""

def __init__(self, UserID, UserName=""):

super(UserHanlde, self).__init__()

if self.UserExsist(UserID):

self.UserInfo = self.LoadUserInfo(UserID)

else:

self.UserInfo = self.CreateNewUser(UserName, UserID)

构造函数,若该用户ID存在则读取状态,否则创建

def UserExsist(self, UserID):

return os.path.exists("./Users/%s.json" % UserID)

判断该ID的JSON文件是否存在

def CreateNewUser(self, UserName, UserID):

UserInfo = {

"name": UserName,

"id": UserID,

"num": 0,

"balance": 50

}

with open("./Users/%s.json" % UserID, "w") as jsonfile:

json.dump(UserInfo, jsonfile, ensure_ascii=False, indent=4)

return UserInfo

创建新用户,将初始余额设为50并保存JSON文件

def LoadUserInfo(self, UserID):

with open("./Users/%s.json" % UserID, "r") as jsonfile:

return json.load(jsonfile)

从JSON文件中载入用户状态

def PlayOneTime(self, Pay):

self.UserInfo["num"] += 1

self.UserInfo["balance"] = self.UserInfo["balance"] - Pay

扣费,扣除指定的费用并在将扣费次数+1

def Recharge(self, Pay):

self.UserInfo["balance"] += Pay

充值,费用加上指定值

def DeleteUser(self):

os.remove("./Users/%s.json" % self.UserInfo["id"])

删除用户,删除指定的JSON文件

def SaveInfo(self):

with open("./Users/%s.json" % self.UserInfo["id"], "w") as jsonfile:

json.dump(self.UserInfo, jsonfile, ensure_ascii=False, indent=4)

保存状态,将当前状态写入对应的JSON文件

Web后端

web后端使用Python的Flask框架构造,代码如下

from flask import Flask, render_template, request

from UserHanlde import UserHanlde

import os

app = Flask(__name__)

def GetUserIDList():

return [x[:-5] for x in os.listdir("./Users") if ".json" in x]

def GetUserInfoList():

UserInfoList = dict()

for UserID in GetUserIDList():

UserData = UserHanlde(UserID)

UserInfoList[UserID] = UserData.UserInfo

return UserInfoList

常用部分的封装:

GetUserIDList():返回已经存在的用户ID列表

GetUserInfoList():返回已经存在的用户状态列表

@app.route("/index")

def ViewInfo():

return render_template("index.html", user_list=GetUserInfoList())

@app.route("/recharge")

def GetReChargeInfo():

return render_template("recharge.html", user_list=GetUserInfoList())

@app.route("/recharge_handle", methods=["GET", "POST"])

def Recharge():

UserID = request.values.get("id")

UserRecharge = request.values.get("pay")

if UserRecharge.isdigit() is True:

UserHanlder = UserHanlde(UserID)

UserHanlder.Recharge(int(UserRecharge))

UserHanlder.SaveInfo()

return render_template("back.html")

else:

return "fail"

@app.route("/register")

def GetRegisterInfo():

return render_template("register.html")

@app.route("/register_handle", methods=["GET", "POST"])

def Register():

UserID = request.values.get("id")

UserName = request.values.get("name")

UserHanlder = UserHanlde(UserID, UserName=UserName)

return render_template("back.html")

@app.route("/pay")

def GetPayName():

return render_template("pay.html", user_list=GetUserInfoList())

@app.route("/pay_handle", methods=["GET", "POST"])

def Pay():

UserIDList = request.values.getlist("vehicle")

UserIDPay = request.values.get("pay")

if UserIDPay.isdigit() is True:

PayNum = int(UserIDPay) / len(UserIDList)

for UserID in UserIDList:

UserHanlder = UserHanlde(UserID)

UserHanlder.PlayOneTime(PayNum)

UserHanlder.SaveInfo()

return render_template("back.html")

else:

return "fail"

路由部分

/index:主页,包括导航和状态显示,所有用户的消费次数和余额将在这里显示

/recharge和/recharge_handle:充值页面, /recharge为操作页面,用户在这里填写表单数据,随后表单数据被提交到/recharge_handle处理充值业务

/register和/register_handle:注册页面,与/recharge和/recharge_handle关系相同

/pay和/pay_handle:扣费页面,与/recharge和/recharge_handle关系相同

app.run(host="0.0.0.0")

运行,监听所有IP,这样在局域网就可以访问了

Web前端

Web使用HTML代码提供GUI,使用Jinja框架分离数据与模板

index界面

index

羽毛球运动管理系统

用户次数余额

{% for user_id in user_list -%}

{{user_list[user_id]["name"]}}{{user_list[user_id]["num"]}}{{user_list[user_id]["balance"]}}

{%- endfor %}

用户状态显示,使用for循环生成表格

超链接部分,用于导航

register界面

register

羽毛球运动管理系统--注册

name

id

back to index

使用两个文本输入框表单输入用户名与用户ID

recharge界面

recharge

羽毛球运动管理系统--充值

{% for userid in user_list -%}

{{user_list[userid]["name"]}}

{%- endfor %}

recharge¥

back to index

使用下拉菜单提供可供选择的用户名,文本输入充值金额

pay界面

pay

羽毛球运动管理系统--消费

{%for userid in user_list%}

{{user_list[userid]["name"]}}

{% endfor %}

pay¥

back to index

使用复选框列出所有用户提供选择,文本输入总输入金额,复选框这种表单数据在后端使用request.values.getlist("name")获取为一个列表

back界面

back

back to index

用户完成充值/注册/消费时用于返回主页


版权声明:本文为weixin_39906521原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。