RELATEED CONSULTING
相关咨询
选择下列产品马上在线沟通
服务时间:8:30-17:00
你可能遇到了下面的问题
关闭右侧工具栏

新闻中心

这里有您想知道的互联网营销解决方案
怎么在Django中利用Highcharts实现数据可视化-创新互联

本篇文章为大家展示了怎么在Django中利用Highcharts 实现数据可视化,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

井研网站制作公司哪家好,找成都创新互联!从网页设计、网站建设、微信开发、APP开发、成都响应式网站建设等网站项目制作,到程序开发,运营维护。成都创新互联自2013年创立以来到现在10年的时间,我们拥有了丰富的建站经验和运维经验,来保证我们的工作的顺利进行。专注于网站建设就选成都创新互联

开发环境

使用 Python 2.7.14,django 1.11.8,highcharts 4.0.1
直接命令行输入以下语句,即可安装django 1.11.8

pip install django==1.11.8

至于Highcharts,可以去官网下载。我用的是之前前辈给的模板,js不是太懂,所以基本没改,只是为了方便进行拓展,对功能模块进行了注释。

开发需求

手头已有爬取的winstore不同app,不同榜单,不同地区的多天rank数据。这些rank数据存放在MySQL服务器中,库名为winstore,表名为winstore_rank。

现在需要将这些rank数据用折线图的方式展示出来。同时在网页上需要可以根据选择的日期,地区,榜单来动态产生折线图。

问题解析

根据开发需求,可以将这次任务分为三个部分。

前端页面

a. ajax动态获取地区列表、榜单列表,生成对应的下拉列表,必要时需将传统下拉列表转换成多选下拉列表

b. 根据搜索结果,将符合条件的app的rank添加到折线图中

服务器端

a. 接受前端的请求,与数据库通信,返回所请求数据

MySQL数据库

a. 根据服务器端传输的sql语句进行对应的查询

根据上述的分析,前端肯定是js + jQuery + Echarts + jquery.multiselect了,服务器端采用Django,数据库方面Django有对应的驱动模块,不用管。

1. 前端页面

新建一个文件rank.html,内容如下:


 {% load static %}
 
 
 
 
 

 
 
 

 
  #set-content ul li #chart {
   width: 60px;
   font-size: 12px;
   height: 22px;
  }
 
 

  // 设定开始日期和结束日期,默认为最近10天
  $(function() {
   $("#beginDate").datepicker({dateFormat: "yy-mm-dd"});
   $("#endDate").datepicker({dateFormat: "yy-mm-dd"});
   var dateNow = new Date();
   var str_dateNow = dateNow.getFullYear() + "-" + (dateNow.getMonth() + 1) + "-" + dateNow.getDate();
   var dateBegin = new Date(dateNow - 10 * 1000 * 3600 * 24);
   var str_dateBegin = dateBegin.getFullYear() + "-" + (dateBegin.getMonth() + 1) + "-" + dateBegin.getDate();
   $("#beginDate").datepicker("setDate", str_dateBegin);
   $("#endDate").datepicker("setDate", str_dateNow);
  });
  // 动态获取数据库中region数据,填充入下拉列表
  $(function() {
   $.get("/getWinstoreRegions",
     {"limit": "0"},
     function(regionsDict) {
      for (var id in regionsDict) {
       regionOption = "" + regionsDict[id] + "";
       $("#region").append(regionOption);
      }
     },
     "json"
     )
  });

  // 动态获取数据库中chart数据,填充入下拉列表
  $(function() {
   $.get("/getWinstoreCharts",
     {"limit": "0"},
     function(chartsDict) {
      for (var id in chartsDict) {
       chartOption = "" + chartsDict[id] + "";
       $("#chart").append(chartOption);
      }
     },
     "json"
     )
  });
  // 动态获取数据库中category数据,填充入下拉列表
  $(function() {
   $.get("/getWinstoreCategories",
     {"limit": "0"},
     function(categoriesDict) {
      for (var id in categoriesDict) {
       categoryOption = "" + categoriesDict[id] + "";
       $("#category").append(categoryOption);
      }
     },
     "json"
     )
  });
  // 动态获取数据库中app名字,填充入下拉列表
  $(function() {
   $.get( "/getWinstoreApps",
    {"limit":"0",},
    function(dataDict) {
     // 循环添加下拉列表的option
     for (var id in dataDict) {
      appOption = "" + dataDict[id] + "";
      $("#appName").append(appOption);
     }
     // 初始化多选
     $("#appName").multiselect({header: false,});
     // 选中所有下拉列表项
     $("#appName").multiselect("checkAll");
     // 动态设置多选框的宽度
     var ulList = $(".ui-multiselect-checkboxes")[0];
     // 必须先单击多选下拉列表,然后才可以获取对应元素的宽度值
     $(".ui-multiselect")[0].click();
     var maxWidth = 0;
     for (var i = 0; i < ulList.childElementCount; i++) {
      var currentInputWidth = $(ulList.childNodes[i]).find("input")[0].offsetWidth;
      var currentSpanWidth = $(ulList.childNodes[i]).find("span")[0].offsetWidth;
      var currentWidth = currentSpanWidth + currentInputWidth * 3;
      if (currentWidth > maxWidth) {
       maxWidth = currentWidth;
      }
     }
     // 设置对应标签的宽度
     $($(".ui-multiselect")[0]).width(maxWidth);
     $($(".ui-multiselect-menu")[0]).width(maxWidth + 6);
     // 二次单击
     $(".ui-multiselect")[0].click();
    },
    "json");
  });
  // 绑定query按钮的单击操作
  $(function() {
   $("#query").click(function() {
    var region = $("#region").val();
    var beginDate = $("#beginDate").val();
    var endDate = $("#endDate").val();
    var chart = $("#chart").val();
    var appNames = $("#appName").val();
    var category = $("#category").val();

    // 将appNames连接成字符串
    queryReport(region, beginDate, endDate, chart, category, appNames.join("@"));
   });
  })
  var lineChart;
  // 获取绘图数据
  function queryReport(region, beginDate, endDate, chart, category, appNames) {
   // 清空原有绘图数据
   $("#container")[0].innerHTML = "";
   // 初始化折线图参数
    var lineChart = new Highcharts.Chart({
            chart: {
             renderTo: 'container',             type: 'line'
            },
            title: {
             text: 'Daily Ranking',
             style: {fontFamily: 'Helvetica', fontWeight: '200'}
            },
            subtitle: {
             text: 'By Product',
             style: {fontFamily: 'Helvetica', fontWeight: '200'}
            },

            xAxis: [{ // master axis
             type: 'datetime',
             gridLineWidth:1,
             gridLineDashStyle: 'longdash',
             tickInterval: 24 * 3600 * 1000,
            }, { // slave axis
             type: 'datetime',
             linkedTo: 0,
             opposite: true,
             tickInterval: 24 * 3600 * 1000,
             labels: {
              formatter: function () {return Highcharts.dateFormat('%a', this.value);}
             }
            }],            tooltip: {
             headerFormat: '{point.key}
',              pointFormat: '\u25AC {series.name}: {point.y}
',             },             yAxis: [{ // Primary yAxis              min:1,              reversed: true,              labels: {               format: 'No. {value}',               style: {                color: '#4572A7'               }              },              title: {               text: 'Ranking',               style: {                color: '#4572A7'                }               }              },              { // Secondary yAxis              min:1,              reversed: true,              title: {               text: 'Ranking',               style: {                color: '#4572A7'               }              },              labels: {              format: 'No. {value}',              style: {               color: '#4572A7'               }              },              opposite: true,             }],             plotOptions: {              column: {               dataLabels: {                enabled: true               },               enableMouseTracking: true              },              line: {               dataLabels: {                enabled: true               },               enableMouseTracking: true              }             },             series: [],            });    // 构造url参数    parameters = {'region': region,       'beginDate': beginDate,       'endDate': endDate,       'chart': chart,       'category': category,       'appNames': appNames       };    // 请求绘图数据    $.get("/getWinstoreRank",      parameters,      function(rankDict) {       var ranksOfApp = new Array();       for (var app in rankDict) {        lineChart.addSeries({         name: app,         data: rankDict[app]        });       }      },      "json"      );   }       
       
  •     Country/Region:          
  •    
  •     Begin Date:          
  •    
  •     End Date:          
  •    
  •     Chart:          
  •    
  •     Category:          
  •    
  •     App:         
  •    
  •     Query    
  •   
 
 

这里稍微解释下,在实际使用中,使用highcharts生成折线图,根据不同的数据,只需要修改series参数即可。而series参数是个啥,可以在上面的HTML代码中搜索series即可。稍微观察下,就明白了。

至于你想换个大饼图,柱状图,可以 点击这里 找现成的例子,稍作修改就可以使用了。当然也许你有更多个性化的需求,那可以 点击这里 找到对应的配置项进行修改。

2. 服务器端

1、首先命令行进入到你想放置项目代码的地方

django_admin startproject winstore

2、进入刚刚新建的项目文件夹

cd winstore

3、创建新的应用rank。这里的应用可以理解成具有独立功能的一组网页的结合,当然在本篇博客里,只有一个网页了。

python manage.py startapp rank

4、在rank文件夹中新建文件夹templatesstatic,将刚刚新建的rank.html放入templates文件夹,同时将引用的js库文件放入static文件夹下,注意文件夹层级。

5.、打开winstore文件夹下的settings.py ,在INSTALL_APPS 下添加rank,添加之后如下:

INSTALLED_APPS = [
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'rank' # 添加的部分
]

DATABASES修改成你自己的MySQL数据库的控制信息。下面是我的数据库设置:

DATABASES = {
 'default': {
  'ENGINE': 'django.db.backends.mysql',
  'NAME': 'winstore', # 数据库名
  'HOST': '127.0.0.1', # IP
  'PORT': '3306',  # 端口号
  'USER': 'root',  # 用户名
  'PASSWORD': '111111', # 密码
 }
}

6、编辑rank文件夹下的views.py文件,在rank.html中加入必要的网页动态功能的实现。由于app的排名数据是根据其所处的榜单chart和应用类别category,以及不同的地区region来确定的,所以这里里的功能实现就需要包括5个部分。分别对appNamechartcategoryregion 实现从数据库动态获取其取值集合以及获取排名数据。对应的实现分别如下:

appName

def getWinstoreApps(request):
 """
 根据接收到的GET请求返回app的取值集合
 """
 # 构造SQL语句
 sql = 'SELECT DISTINCT appName FROM winstore_rank'
 # 默认appNames的key和value相同
 appNames = {}
 try:
  result = getDataFromSQL(sql)
  result = [r[0] for r in result]
  for key in result:
   appNames[key] = key
 except Exception as e:
  print('getWinstoreApps ERROR: ' + str(e))
  appNames['QQ'] = 'QQ'
 return JsonResponse(appNames)

chart

def getWinstoreCharts(request):
 """
 根据接收到的GET请求返回chart的取值集合
 """
 # 构造SQL语句
 sql = 'SELECT DISTINCT chart FROM winstore_rank'
 # 默认charts的key和value相同
 charts = {}
 try:
  result = getDataFromSQL(sql)
  result = [r[0] for r in result]
  for key in result:
   charts[key] = key
 except Exception as e:
  print('getWinstoreCharts ERROR: ' + str(e))
  charts['Free'] = 'Free'
 return JsonResponse(charts)

category

def getWinstoreCategories(request):
 """
 根据接收到的GET请求返回category的取值集合
 """
 # 构造SQL语句
 sql = 'SELECT DISTINCT category FROM winstore_rank'
 # 默认categories的key和value相同
 categories = {}
 try:
  result = getDataFromSQL(sql)
  result = [r[0] for r in result]
  for key in result:
   categories[key] = key
 except Exception as e:
  print('getWinstoreCategories ERROR: ' + str(e))
  categories['Education'] = 'Education'
 return JsonResponse(categories)

region

def getWinstoreRegions(request):
 """
 根据接收到的GET请求返回region的取值集合
 """
 # 构造SQL语句
 sql = 'SELECT DISTINCT region FROM winstore_rank'
 # 默认regions的key和value相同
 regions = {}
 try:
  result = getDataFromSQL(sql)
  result = [r[0] for r in result]
  for key in result:
   regions[key] = key
 except Exception as e:
  print('getWinstoreRegions ERROR: ' + str(e))
  regions['EN-US'] = 'EN-US'
 return JsonResponse(regions)

获取排名数据

def getWinstoreRank(request):
 """
 根据接收到的GET请求返回对应app的排名数据
 """
 # 从GET请求中获取参数
 region = request.GET.get("region", "EN-US")
 chart = request.GET.get("chart", "Free")
 category = request.GET.get("category", "Education")
 beginDate = request.GET.get("beginDate", "2018-01-22")
 endDate = request.GET.get("endDate", "2018-02-02")
 appNames = request.GET.get("appNames", "QQ").split("@")
 # 构造SQL语句
 sqlTemp = 'SELECT the_date, rank FROM winstore_rank WHERE ' \
    'region="%s" AND chart="%s" AND category="%s" AND ' \
    'the_date BETWEEN "%s" AND "%s" AND ' \
    'appName=' % (region, chart, category, beginDate, endDate)

 # 以每个appName作为key,对应的排名数据列表作为value
 appRank = {}
 for appName in appNames:
  sql = sqlTemp + '"' + appName + '"'
  try:
   result = getDataFromSQL(sql)
   # 根据数据库返回的结果将缺少rank数据的日期补0
   result = addZeroToRank(beginDate, endDate, result)
   appRank[appName] = result
  except Exception as e:
   print('getWinstoreRank ERROR: ' + str(e))
 return JsonResponse(appRank)


def addZeroToRank(beginDate, endDate, result):
 """
 以beginDate和endDate为日期的起始,将result中缺少的日期补全,同时设定排名为0
 Param:
  beginDate: 开始日期字符串,“2018-01-23”
  endDate: 结束日期字符串, “2018-02-02”
  result: 形如[(date, 23L), (date, 12L), [date, 3L]......]
 Return:
  按照日期顺序排列的排名数据,缺省排名为0
 """
 # 将日期字符串转变为date类型数据,方便日期加减
 y, m, d = [int(i) for i in beginDate.split("-")]
 begin = datetime.date(y, m, d)
 y, m, d = [int(i) for i in endDate.split("-")]
 end = datetime.date(y, m, d)
 current = begin
 # 获取result中的日期,方便进行判断
 resultTemp = [r[0] for r in result]
 while current <= end:
  if not (current in resultTemp):
   result.append((current, 0))
  current += datetime.timedelta(days=1)
 result.sort(key=lambda x: x[0])
 return [int(r[1]) for r in result]

这里主要就是构造SQL语句,然后访问数据库获取对应的数据集合。其中getDataFromSQL() 是对访问MySQL数据库的简单封装,具体代码如下:

def getDataFromSQL(sql):
 """
 根据sql语句获取数据库的返回数据
 """
 cursor = connection.cursor()
 cursor.execute(sql)
 return list(cursor.fetchall())

一些涉及到的引用可以参考文末给出的项目代码。

最终绑定一下首页

def index(request):
 """
 绑定网站首页
 """
 return render(request, 'rank.html')

3. MySQL数据库

实际应用时,相关的rank数据是通过爬虫获取的。在这里,就直接填充一些随机的rank数据进去了,不影响最终的结果。

最终成果展示

首页

怎么在Django中利用Highcharts 实现数据可视化

rank数据展示

怎么在Django中利用Highcharts 实现数据可视化

可以看到虽然前端页面很简陋,但是功能是实现了。不过有个问题 就是重新点击query按钮后,highcharts提供的右侧页面中间下载图片的那个三道杠会出现并排的两个。

上述内容就是怎么在Django中利用Highcharts 实现数据可视化,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。


标题名称:怎么在Django中利用Highcharts实现数据可视化-创新互联
转载来于:http://lswzjz.com/article/decish.html