使用 chart.js 从 django 创建动态图表

Posted

技术标签:

【中文标题】使用 chart.js 从 django 创建动态图表【英文标题】:Creating a dynamic chart from django using chart.js 【发布时间】:2022-01-17 01:26:16 【问题描述】:

我是 Django 新手。我目前正在通过 Twitter API 对实时用户推文进行情绪分析。我已经设法进行分析并显示情绪。现在,我想在我的 Django 应用程序中使用图表(可能是条形图或饼图)将情绪可视化,但我不确定如何。

我正在考虑使用 Chart.js 使其具有响应性,但大多数示例都使用静态数据,因此我无法成功地将我从 Twitter API 中提取的数据与 chart.js 集成。

这是我的网页截图。该表是提取的推文及其相应的情绪。然而,条形图只是静态数据。不知道怎么转成json。

screenshot of my webpage

这是我的views.py

from django.http.response import JsonResponse
from django.shortcuts import render, redirect, HttpResponse
from .forms import Sentiment_Typed_Tweet_analyse_form
from .sentiment_analysis_code import sentiment_analysis_code
from .forms import Sentiment_Imported_Tweet_analyse_form
from .tweepy_sentiment import Import_tweet_sentiment
from django.contrib.auth.decorators import login_required
from django.contrib import messages
      
def sentiment_analysis_import(request):
    if request.method == 'POST':
        form = Sentiment_Imported_Tweet_analyse_form(request.POST)
        tweet_text = Import_tweet_sentiment()
        analyse = sentiment_analysis_code()

        if form.is_valid():
            handle = form.cleaned_data['sentiment_imported_tweet']
            # messages.info(request, 'It might take a while to load the data.')

            if handle[0]!='#':
                list_of_tweets = tweet_text.get_hashtag(handle)
                list_of_tweets_and_sentiments = []
                for i in list_of_tweets:
            

    list_of_tweets_and_sentiments.append((i,analyse.get_tweet_sentiment(i)))
                args = 'list_of_tweets_and_sentiments':list_of_tweets_and_sentiments, 'handle':handle
                return render(request, 'home/sentiment_import_result_hashtag.html', args)
            
            if handle[0]=='#':
                list_of_tweets = tweet_text.get_hashtag(handle)
                list_of_tweets_and_sentiments = []
                for i in list_of_tweets:
                    list_of_tweets_and_sentiments.append((i,analyse.get_tweet_sentiment(i)))
                args = 'list_of_tweets_and_sentiments':list_of_tweets_and_sentiments, 'handle':handle
                return render(request, 'home/sentiment_import_result_hashtag.html', args)
            
    else:
        form = Sentiment_Imported_Tweet_analyse_form()
        return render(request, 'home/sentiment_import.html')

def get_data(request, *args, **kwargs):
def get_data(request, *args, **kwargs):
    sentiment_analysis_import(args)
    data = 
        args
    
    return JsonResponse('home/sentiment_import_result_hashtag.html', data)

这是我的 HTML

    <!DOCTYPE html>
<html lang="en">
% load static %
  <head>
    <title>Sentymeter: Import Tweets</title>
   <!-- Required meta tags -->
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
   <!-- Bootstrap CSS -->
   <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <!--Chart js-->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.js" integrity="sha256-Uv9BNBucvCPipKQ2NS9wYpJmi8DTOEfTA/nH2aoJALw=" crossorigin="anonymous"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" integrity="sha256-aa0xaJgmK/X74WM224KMQeNQC2xYKwlAt08oZqjeF0E=" crossorigin="anonymous" />
    <!-- jQuery -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
   <title>Import Tweets</title>

   <style>
     .tbl-header 
      border: 5px solid;
        background-color: #fff;
    
     table 
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 100%;


td, th 
  border: 1px solid #dddddd;
  text-align: left;
  padding: 8px;


th
  color: white;
  background: black;


tr:nth-child(even) 
  background-color: #e4e9e4;

tr:nth-child(odd) 
  background-color: #c2c2c2;


body,
        html 
            margin: 0;
            padding: 0;
            height: 100%;
            background: #f8f2ce !important;
        
    h7.white-text 
         color: rgb(255, 255, 255);
        
    
</style>
   </style>
   </head>
   <body>

  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarSupportedContent">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item">
              <a class="nav-link" href="/">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="/sentiment/type">Input Text</a>
        </li>
              <li class="nav-item active">
                  <a class="nav-link" href="/sentiment/import">Import Tweets<span class="sr-only">(current)</span></a>
              </li>
              <li class="nav-item">
                  <a class="nav-link" href="/feedback">Feedback</a>
              </li>
          </ul>
      </div>
      <span class="hello-msg"><strong>Hello, request.user</strong></span>&nbsp;&nbsp;&nbsp;
      <button class="btn btn-danger navbar-btn" ><a href="% url 'user:logout' %"><h7 class="white-text" color=white;>Logout</h7></a></button>
  </nav>


      <div class="container">
        <div class="row align-items-center ftco-vh-100">
          <div class="col-md-9">
            <h1 class="ftco-heading mb-3" >Import Tweets Result</h1>
            <h2 class="h5 ftco-subheading mb-5" ><strong>Keyword</strong> -  handle </h2>
      </div><div></div>   
      
      <div class = "container">
      
      <h1>test</h1>
    </div>
    <div class="col-sm-4">
    <canvas id="myChart"  ></canvas>

   list_of_tweets_and_sentiments|json_script:"list_of_tweets_and_sentiments" 
<!-- <script>
  const ctx = JSON.parse(document.getElementById('list_of_tweets_and_sentiments').textContent);
</script> -->


<script>
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, 
    type: 'bar',
    data: 
        labels: ['Positive', 'Neutral', 'Negative'] ,
        datasets: [
            label: 'Sentiment Counts',
            data: [12, 19, 3],

            backgroundColor: [
                'green',
                'orange',
                'red',
            ],
        ]
    ,
    options: 
        scales: 
            y: 
                beginAtZero: true
            
        
    
);
</script></div>
 

<div class="tbl-header" >
    <table>
        <tr>
          <th >Tweet</th>
          <th>Sentiment</th>
          <th>Emotag</th>
        </tr>
      <tbody>
        % for i,j in list_of_tweets_and_sentiments %
        <tr>
          <td>i</td>
          <td>j</td>
          % ifequal j 'Negative' %
          <td><img src="% static 'icons/negative.png' %"></td>
          % endifequal %
          % ifequal j 'Positive' %
          <td><img src="% static 'icons/positive.png' %"></td>
          % endifequal %
          % ifequal j 'Neutral' %
          <td><img src="% static 'icons/neutral.png' %"></td>
          % endifequal %
        </tr>
        % endfor %
      </tbody>
    </table>
  </div>


<h1>test</h1>


<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>


  </body>
</html>

谁能帮助我将我的情绪推文与图表联系起来?我现在很迷茫……

如果您需要其他文件/代码,请告诉我。

【问题讨论】:

【参考方案1】:

在大多数情况下 Chart.js 除了数组或 JSON 格式的 api 调用。

如果您使用的是 Django,您可以创建要在模板和数据数组中使用的变量,例如:

Sentiment.filter(neutral=True).count() # return the number based on a specific filter

将其传递给变量并在数据数组中的模板中:

data: [neutral_sentiment, positive_sentiement, negative_sentiment], 

-> 包含用于生成图表的数字的变量

在大多数情况下,我会这样做,如果您的数据不复杂并且您没有获取数千个查询,它会很好地工作。

【讨论】:

你能详细说明一下如何编码吗?我仍然对将Sentiment.filter(neutral=True).count() 放在哪里感到有些困惑。我是把它放在views.py 中还是放在 HTML 模板中,但是放在哪里? 把它放在views.py中,并将它分配给你在render方法中的args字典中的一个变量,例如'neutral': Sentiment.filter(neutral=True).count ()

以上是关于使用 chart.js 从 django 创建动态图表的主要内容,如果未能解决你的问题,请参考以下文章

使用AJAX请求json类型的列表数据从chart.js动态输出到气泡图中

图表未显示在Django应用程序的Web页面上(使用Chart.js)

Django:将日期列表传递给 Chart.js 模板中的 JavaScript

从 jsonfile 数据创建多个 chart.js 图表

在 Django 模板中使用 for 循环显示多个 chart.js 图表

winform cefsharp chart.js 再winform上使用chart.js 绘制动态曲线