开发日记----数据监控web系统开发项目

在开始总结这个数据监控系统开发项目之前,
必须要感叹一下,真是不容易啊。完成开发任务的时候,还要去完成毕业的事情,两地奔波,几乎没有休息。
最后弄得自己大病一场,连续几日的高烧不退,在医院打点滴的时候,不停地问自己,这么拼值得么。
我想,我已经付出了代价了,如果不能收获点什么,有所成长,那才是最不值得的事情。

数据监控web系统开发项目 是我参加工作以来,第一个正式的开发项目。前后端分离的web项目。
而我主要负责的是后端的开发,用的是 Django 2.1.8 的后端开发框架,由另一个同事负责前端的开发工作,用的是vue.js

项目的背景:在公司的业务中,常需要用到几张数据表格,但之前都是人工维护,因此会导致几张表格之中会出现数据不统一,并且难发现的情况。(共有5表格,如A B C D E)其中B 对应为A的每日数据,C为B 与 D的对比数据结果。E(用户表)
项目总需求:数据表格入库,入库后对数据进行提取对比生成监控数据,对有问题数据进行问题标注。
项目后端需求:编写 A数据表格,单条添加,批量导入。编辑,查询接口。
B数据表格,批量导入。编辑,查询接口。
C表格,查询接口
-----------------------------------------------------------------背景介绍完毕-----------------------------------------------------------------------------------------
第一天开始开发时,和同事了解过几遍,每个需求的具体实现,还有数据表的具体设计。
首先是常规的 django-admin.py startproject project_name 创建项目
python manage.py startapp xxx 创建项目应用
由于我们先建好了数据库,因此修改好同名文件夹中setting.py的设置后 python manage.py inspectdb >models.py 反向生成
接着就可以开始写业务代码了。
由于编辑,添加,各个表之间存在业务逻辑,因此我就先写了各个表的查询接口。

res_msg= {'recode':1,'errorMessage':None,'content':[]}
def A_get(request):
    error_logging.error('station_arrange_get的请求参数:' + '||' + str(request.POST))
    res = res_msg
    try:
        res = res_msg
        query_data_dict = {}
        station_month = request.POST.get("station_month", None)
        if station_month:
            error_code = judge_month(station_month)
            if error_code:
                res['recode'] = 0
                res['errorMessage'] = 'station_month错误'
                res['content'] = []
                error_logging.error('error_code:'+str(res['recode']) + '||' + res['errorMessage'])
                res = json.dumps(res, cls=DjangoJSONEncoder, ensure_ascii=False)
                return HttpResponse(res)
            else:
                query_data_dict["station_month"] = station_month

        # 项目名称
        brand = request.POST.get("brand", None)
        if brand:
            error_code = judge_string(brand)
            if error_code:
                res['recode'] = 0
                res['errorMessage'] = 'brand有误'
                res['content'] = []
                error_logging.error('error_code:' + str(res['recode']) + '||' + res['errorMessage'])
                res = json.dumps(res, cls=DjangoJSONEncoder, ensure_ascii=False)
                return HttpResponse(res)
            else:
                query_data_dict['brand__icontains'] = brand
                。。。。。
               这里一共有30多个参数,参数的代码结构均一致,因此就不一一展示了。
         
        order_by = request.POST.get("order_by", 'station_id')
        if order_by:
            error_code = judge_string(order_by)
            if error_code:
                res['recode'] = 0
                res['errorMessage'] = 'order_by' + '有误'
                res['content'] = []
                error_logging.error('error_code:' + str(res['recode']) + '||' + res['errorMessage'])
                res = json.dumps(res, cls=DjangoJSONEncoder, ensure_ascii=False)
                return HttpResponse(res)
        else:
            order_by='station_id'
        is_ascend = request.POST.get("is_ascend", '1')
        最后这里是排序的参数,由于前端排序过程中会传""这样的空字符,因此另外对  order_by='station_id' 进行单独赋值
         if len(query_data_dict)>0:
              # 根据查询条件查询
              #显示筛选数据
              A_obj = models.A.objects.filter(**query_data_dict)
              # 将查询到数据对象转换成字典,添加到data_list中
              for a_obj in A_obj :
                  a_obj_dict = model_to_dict(a_obj )
                  a_obj_dict ['update_tms'] = a_obj .update_tms
                  a_obj_dict ['user_name'] = a_obj .uid.name
                  data_list.append(a_obj_dict )

          else:  # 默认显示数据
              A_obj =models.A.objects.all()
               for a_obj in A_obj :
                  a_obj_dict = model_to_dict(a_obj )
                  a_obj_dict ['update_tms'] = a_obj .update_tms
                  a_obj_dict ['user_name'] = a_obj .uid.name
                  data_list.append(a_obj_dict )

		if is_ascend == '1':
			reverse = False
	    elif is_ascend == '0':
			reverse = True
	     data_list = sorted(data_list, key=lambda x: x[order_by], reverse=reverse)
          
         res['recode'] = 1
         res['errorMessage']=None
         res['content']=data_list
         
         res = json.dumps(res, cls=DjangoJSONEncoder, ensure_ascii=False)
         return HttpResponse(res)
         

比如我们之前讨论过的A表中有一个起始时间段和结束时间段,B表中则是对应,该时间段的A表的每日数据的相应说明。同时查询时,需要返回关于该条数据在A中的部分字段,其中涉及到了联合查询。
当初,在讨论时,同事表示数据表结构设计不使用关联,因此使用orm多次查询导致性能特别差,后来反复商榷后改成关联关系,A表作外键关联至B表。

B_obj = models.B.objects.filter(**query_data_dict).values(
	  'station_id',
	    'station__station_name',
	    'station__station_month',
	    'station__executive_supplier',
	    'station__edition',
	    'station__brand',
	    'date',
	    'date_type',
	    'conclusion_abnormal',
	    'output_sign',
	    'estimated_entry',
	    'end_sign',
	    'camera_abnormal',
	    'mbox_abnormal',
	    'remark',
	    'abnormal_sign',
	    'update_tms',
	    'insert_tms',
	    'uid__name',
        )
        # import  pdb
        # pdb.set_trace()
        for b_obj in B_obj :
            b_obj ["station_name"] = b_obj .pop("station__station_name")
            b_obj ["station_month"] = b_obj .pop("station__station_month")
            b_obj ["brand"] = b_obj .pop("station__brand")
            b_obj ["executive_supplier"] = b_obj .pop("station__executive_supplier")
            b_obj ["edition"] = b_obj .pop("station__edition")
            b_obj ["user_name"] = b_obj .pop("uid__name")
            data_list.append(b_obj )

        if is_ascend == '1':
            reverse = False
        elif is_ascend == '0':
            reverse = True

        data_list = sorted(data_list, key=lambda x: x[order_by], reverse=reverse)
        res['recode'] = 1
        res['errorMessage'] = ''
        res['content'] = data_list
        

整个查询接口的业务代码,大致上就是这样。还有一些异常捕获处理,就没有补上了。包括B表,C表的查询接口也是大同小异,只是需要返回的参数不同。

当查询接口都写完之后,就开始着手,新增的业务逻辑了。

AB
新增一条数据,时间为2019-6-1到2019-6-3B中新增,与A相应的3条数据,分别为2019-6-1,2019-6-2,2019-6-3

因此A表 新增接口 从前端获取完参数之后,利用Django的orm 新增数据记录
同时将时间提取处理,自动新增B表中的数据记录

为B表记录添加默认参数
query_data_dict = {
        "station_id": station_id,
        "output_sign": 1,
        "end_sign": 0,
        "abnormal_sign": '0',
        "uid": uid,
    }
start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d").date()
end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d").date()
B_create(start_date, end_date, **query_data_dict)

B表中,创建数据记录的方法如下
def B_create(start_date, end_date, **query_data_dict):
	len_day = abs((end_date - start_date).days)
    for i in range(len_day + 1):
        date = start_date + datetime.timedelta(days=i)
        query_data_dict["date"] = date
        if date.weekday() < 5:
            query_data_dict["date_type"] = "工作日"
        else:
            query_data_dict["date_type"] = "休息日"
        new_B = models.B.objects.create(**query_data_dict)
        

然后就开始写 A,B 的编辑接口。
同样的,也是接受前端发送过来的参数,然后根据参数去修改数据库中相应的数据内容。是不是一开始听到,觉得很简单。但其中是由几个小坑的。修改的字段中,起始时间,和结束时间字段,一但修改了A的时间字段,那么B中的数据也要进行相应的调整,多的时间段数据就要删除,少的时间段就要补齐。

为此我整理所有的可能性。

# A--B 为修改后的时间段 a--b为修改前的时间段
# ----A---B---a---b--        (1)
# ----A---B(a)---b--        (1-1)相等
# 或 ----a---b-A----B---     (2)  全删除重建
# ----a---b(A)----B----       (2-2)相等

# 或---A--a----B---b---      (3)  删除并新建
# 或 ----a-A---B--b--        (4)  删除前后多余的
# 或 ----a-A--b--B----       (5)  删除并新建

# 修改的时间出现相同时
# 或 ----a(A)--B---b--        (7) 删除多余
# 或 ----a(A)--b---B-         (8) 新建
# 或 ----a--A--b(B)-           (9)  删除多余
# 或 ----A--a----b(B)--        (10) 新建
# 或 ----(A)a----b(B)--        (11) 无操作
# 补充情况
# 或 --A--a---b--B----       (12)  新建

并对每一种情况作相应的业务处理。

来到这里的我,曾天真地认为把导入接口完成了,就大功告成了。
实则,还有很多业务上的坑,在等着我。
比如 C表中 会出现 即B表无该天数据,但D表有该天数据的情况 或者 即D表无该天数据,但B表有该天数据的情况
这两种特殊情况都要生成相应的监控数据。

监控逻辑说明图
在部门老大的梳理下,把各种异常情况都总结了出来,其实就是用0 1 -1 分别代表不出数,出数,和无数据,以此来对监控数据进行填充。
最后就剩下导入功能的实现了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值