django:数据收集与统计可视化的简单设计

django:数据收集与统计可视化的简单设计

あつまれ どうぶつの森中,每周日的上午(12:00前)可以购买大头菜,而周一到周六可在卖出大头菜。大头菜的价值是会浮动的,每天闭店时和中午12:00分别更新一次,也就是每周有12次的价格变动,如果在一周之内没有把菜卖掉,那么周日这些菜就会变成烂菜,不能再卖。

大头菜实际上就是芜菁,日语中叫作 カブ ,与日语中的股份一词“かぶ” 同音,这个游戏机制确实有点像只有1支股的股票交易。

switch肯定没有API,数据只能手动输入。现在要设计一个统计系统,就是将历来的大头菜数据都收集起来,每周日进行归档。

由于服务运行在本地,就没有连接数据库,数据都存储在文件当中。处理逻辑是这样的:主页显示了本周和上周的购入价格和卖出价格曲线。如果检查到当前时段的价格还没有填入,表单就处于显示状态,可以填写当前的价格,填写后保存数据并跳转回主页。

效果展示:

django是MVC开发模式,初始化一个django项目之后,urls.py当中定义的是各种url访问入口,views.py定义的是各种处理函数代表控制器(C),Models.py当中定义的是数据模型(M),一般在template文件夹下的各个模板文件代表视图(V).

创建一个项目,起名为Brassica(大头菜),并在 Brassica/下建立文件夹template和data,template存放HTML模板,data存放数据。项目Brassica/下打开settings.py,将其中的TEMPLATES=[‘DIRS’:[]…]改为

TEMPLATES=[...
        'DIRS': [BASE_DIR+"/Brassica/templates/"], 
           ...]

这样程序可以在这个路径下找到我们的模板文件。

在urls.py中,修改为如下形式,这样就可以执行跳转。

from django.conf.urls import url
from . import index,fillData

urlpatterns = [
    url(r'^fillNewData',fillData.saveData),
    url(r'', index.home),
]

接下来就设计index.py中的home()函数和fillData.py中的saveData函数。

新建一个index.py用于控制主页的显示

from django.shortcuts import render

import os
import datetime

def saveThisPeriodData(request,price):
    pass



def isNeedToInputData(theData,fName):
    fp = open(fName)
    msg = fp.read().split("\n")
    if (theData.weekday()==6):
        if msg[0]=="0":
            return True
    else:
        idx = 2*theData.weekday()
        if(theData.hour>=12):
            idx+=1
        r = eval(msg[1])
        if(len(r)==0):
            return True
        elif idx != r[-1][0]:
            return True
    return False


def home(request):
    nowData = datetime.datetime.now()

    def getThisSunday(now):
        
        if(nowData.weekday()==6):
            return nowData
        else:
            return  nowData-datetime.timedelta(days=1+nowData.weekday())

    def getLastSunday(thisSunday):
        return thisSunday-datetime.timedelta(days=7)


    thisSunday = getThisSunday(nowData)
    lastSunday = getLastSunday(thisSunday)

    fName = "Brassica/data/"+"{:04d}{:02d}{:02d}".format(thisSunday.year,thisSunday.month,thisSunday.day)

    
    if not (os.path.exists(fName)):
        with open(fName,"w") as fp:
            fp.write("0\n[]\n")
    
    fp=open(fName)
    msg = fp.read().split("\n")
    ctx = {}
    if not isNeedToInputData(nowData,fName):
        ctx["inputFrame"]="none"
    ctx["BoughtPrice"]=msg[0]
    ctx["priceList"]=msg[1]
    fp.close()
    ctx["currTime"] =  nowData
    weekdayToChar = "一二三四五六日"
    ctx["weekDay"] = weekdayToChar[datetime.datetime.now().weekday()]

    fName = "Brassica/data/"+"{:04d}{:02d}{:02d}".format(lastSunday.year,lastSunday.month,lastSunday.day)

    fp=open(fName)
    msg =fp.read().split("\n")
    ctx["lastSundayBoughtPrice"] = msg[0]
    ctx["lastWeekPriceList"] = msg[1]
    fp.close()

    return render(request,"index",ctx)

以及用于存储数据的post响应

from django.shortcuts import render
from django.views.decorators import csrf

import datetime

def saveData(request):

    nowData = datetime.datetime.now()
    if request.method=="POST" and request.POST:

        def getThisSunday(theData):
            
            if(theData.weekday()==6):
                return theData
            else:
                return  theData-datetime.timedelta(days=1+theData.weekday())
        
        thisSunday = getThisSunday(nowData)

        fName = "Brassica/data/"+"{:04d}{:02d}{:02d}".format(thisSunday.year,thisSunday.month,thisSunday.day)
        fp = open(fName,"r")
        msg = fp.read().split("\n")
        fp.close()
        print(msg)

        fp=open(fName,"w")
        if(nowData.weekday()==6):
            fp.write(request.POST['price']+"\n[]")
        else:
            idx = 2*nowData.weekday()
            if(nowData.hour>=12):
                idx+=1
            r = eval(msg[1])
            r.append( [idx,int(request.POST["price"])] )

            fp.write(msg[0]+"\n"+str(r))
        fp.close()

    return render(request,"post")

    

主页对应的模板:

<html>
<head>
<meta charset="UTF-8" />
<title>菜价</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.highcharts.com.cn/highcharts/highcharts.js"></script>
<script src="https://code.highcharts.com.cn/highcharts/highcharts-more.js"></script>
<script src="https://code.highcharts.com.cn/highcharts/modules/exporting.js"></script>
<script src="https://img.hcharts.cn/highcharts-plugins/highcharts-zh_CN.js"></script>
<script src="https://code.highcharts.com.cn/highcharts/themes/grid-light.js"></script>
</head>
<body>
<div>
{{currTime}}<br> 星期{{weekDay}}
<br>

<form style="display:{{inputFrame}}" action="/fillNewData" method="post">
    {% csrf_token %}
    <p>当前菜价
        <input type="text" name="price"/>
    </p>
    <input type="submit" value="Submit">
</form>

</div>
   <div id="container" style="width: 1200px; height: 600px; margin: 0 auto"></div>
   <script language="JavaScript">
      
      var chart = Highcharts.chart('container', {
    chart: {
         type:'spline',
        plotBorderWidth: 1,
        zoomType: 'xy'
    },
    legend: {
        enabled: false
    },
    title: {
        text: '大头菜价格统计'
    },
    		legend: {
				layout: 'vertical',
				align: 'right',
				verticalAlign: 'middle'
		},
    
    xAxis: {
        gridLineWidth: 1,
        title: {
            text: '时间'
        },
        categories: ['Mon A.M.', 'Mon P.M.', 'Tue A.M.', 'Tue P.M.', 'Wed A.M.', 'Wed P.M.',
                     'Thu A.M', 'Thu P.M.', 'Fri A.M.', 'Fri P.M', 'Sat A.M.', 'Sat P.M.']
    },
    yAxis: {
        startOnTick: false,
        endOnTick: false,
        title: {
            text: '菜价'
        },
        maxPadding: 0.2,
        plotLines: [{
            color: 'red',
            dashStyle: 'ShortDash',
            width: 2,
            value: {{BoughtPrice}},
            label: {
                align: 'right',
                text:'周日购入价格:{{BoughtPrice}}',
                x: -10
            },
            zIndex: 3
        },
        {
            color: 'black',
            dashStyle: 'dot',
            width: 2,
            value: {{BoughtPrice}},
            label: {
                align: 'left',
                text:'上周日购入价格:{{lastSundayBoughtPrice}}',
                x: 10
            },
            zIndex: 3
        }
        ]
    },

    plotOptions: {
        series: {
            dataLabels: {
                enabled: true,
                format: '{point.name}'
            }
        }
    },
    series: [{
        
        name:"本周",
        data: 
        {{priceList}}
    },
    {
        name:"上周",
        data:
        {{lastWeekPriceList}}
    }]
});
   </script>
</body>
</html>

POST请求对应的模板只需要1句话,跳转回主页即可

<script >window.location.href="/"</script >

这样,回到上一级目录,运行

python manage.py runserver 8809

就可以在端口8809运行程序

发表评论

电子邮件地址不会被公开。 必填项已用*标注