something wrong in presenting highcharts using django - django

I was stuck in passing dict's data to highchart using django
here's my views.py code. My thought is trying to pass the database's data to dictionary data , then pass its to user_chart.html's highchairs
def user_chart(request):
user_data = User_Data.objects.filter(user=request.user.username)
data = {'words':[], 'click_times':[]}
for i in user_data:
data['words'].append(i.word)
data['click_times'].append(i.click_times)
xAxis = {"title": {"text": 'ss'}, 'categories': data['words']}
yAxis = {"title": {'text': 'fdfd'}}
series = [
{"name": 'dfdf', "data": data['click_times']}
]
content = {'xAxis': xAxis, 'yAxis': yAxis, 'series': series}
return render(request, 'yigu/user_chart.html', content)
user_chart.html's code. I want to achieve a goal that highchart receives the data then present its as chart.
{% extends 'yigu/base_charts.html' %}
{% block body_block %}
<div class="container">
<div class="row">
<div class="col-md-1"></div>
<div class="col-md-1"></div>
<div class="col-md-1"></div>
<div class="col-md-1">
<div id="chart1" style="width:450px">
</div>
</div>
<div class="col-md-4"></div>
</div>
</div>
<script>
var xAxis = {{ xAxis|safe }}
var yAxis = {{ yAxis|safe }}
var series = {{ series|safe }}
</script>
<script>
$(document).ready(function(){
$("#chart1").highcharts({
chart: {
type: 'column'
},
title: {
text: '搜索频率'
},
xAxis: xAxis,
yAxis: yAxis,
series: series
});
});
</script>
{% endblock %}
But i just got the blank response, the chart didn't show up. Anyone could give me a hand?

After reading http://blogs.law.harvard.edu/rprasad/2011/08/30/highcharts-django-admin/ I noticed categories: [ '{{ categories|join:"','" }}'] And i thought that maybe i should try this type. Then i change my template into something like below
<script>
$(document).ready(function(){
$("#chart1").highcharts({
chart: {
type: 'column'
},
title: {
text: '搜索频率'
},
xAxis: {
title:{
text: '词条',
},
categories: [ '{{ data.words|join:"','"}}']
},
yAxis: {
title:{
text: '次数'
}
},
series:[{
name:'搜索次数',
data:[{{ data.click_times|join:"," }}]
}]
});
});
</script>
Then everything went right. I was so surprised. I hope the solution would help someone.

Related

Django chart.js multi axis line chart

Hi Guys I have inspired from this Fiddle example to try to create a similar multi axis line chart in my django project.
I have in my views :
class dashboard(TemplateView):
template_name = 'users/dashboard.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['qs'] = DummyData.objects.all()
data = DummyData.objects.all()
years=[]
for i in range(data.count()) :
if data[i].year not in years :
years.append(data[i].year)
context['years'] = years
return context
in in my dashboard.html :
{% extends 'users/base.html' %} {% load static %} {% block content %}
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- semantic UI -->
<link rel="stylesheet" type='text/css' href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.14/semantic.min.css">
<!--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>
<script>
$(document).ready(function (){
var ctx = document.getElementById('myChart');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [{% for year in years %} '{{year}}', {% endfor %}],
datasets: [{% for item in qs %}
{
label: '{{item.site}}',
yAxisID: '{{item.site}}',
data: [100, 96, 84, 76, 69] , {% endfor %}
]
},
options: {
scales: {
yAxes: [{
id: 'A',
type: 'linear',
position: 'left',
}, {
id: 'B',
type: 'linear',
position: 'right',
ticks: {
max: 1,
min: 0
}
}]
}
}
});
});
</script>
<canvas id="myChart" width="400" height="100"></canvas>
{% endblock content %}
When I copied the fiddle example it showed correctly in my dahsboard.html as follows :
But When I tried to change the datasets in the code as presented in my dashboard.html nothing shows up, labels are updated okay but this is what makes my chart not work :
datasets: [{% for item in qs %}
{
label: '{{item.site}}',
yAxisID: '{{item.site}}',
data: {{item.turn_over}}' , {% endfor %}
]
I am sure this is not how it is supposed to be done, I'm a beginner at chart.js , what I want to do is load how many sites I have in my Dummydata table and show their turn over
Thank you
Done It was a comma positioning mistake, I checked the console and the problem was that when my if condition was not being checked instead of skipping, it was adding an empty value, meaning that I was getting for example 1, , , , 2 , , , 3 instead of 1,2,3 and the chart was rendering the empty cells, anyway here is the how I was able to fix it for data :
data: {
labels: [{% for year in years %} '{{year}}', {% endfor %}],
datasets: [
{% for site in sites %}
{
label: '{{site.site}}',
yAxisID: 'y',
borderColor: '{{site.color}}',
backgroundColor: 'transparent',
data: [ {% for item in qs %}
{% if item.site == site.site %}
{{item.turn_over}} ,{% endif %} {% endfor %}
]
}, {% endfor %}
]
}

Data not displaying in django admin - using chart.js (no errors)

I have created a changelist_view for displaying a chart.js visual in the Django admin.
I am not getting any errors, the chart outline is visible, but the data is not. Not sure what I'm missing. Info below:
admin.py model:
class MachineFaultAdmin(admin.ModelAdmin):
readonly_fields = [
'event_id',
'fault_type_id',
'position',
]
list_display = [
'event_id',
'fault_type_id',
'position',
]
def changelist_view(self, request, extra_context=None):
# Aggregate Faults
chart_data = (
MachineFault.objects.all()
.values('position')
.annotate(total=Count('fault_type_id'))
.order_by('total')
.filter(position__gte=10)
)
#Serialize and attach the chart data to the template context
as_json = json.dumps(list(chart_data), cls=DjangoJSONEncoder)
extra_context = extra_context or {"chart_data": as_json}
#Call the superclass changelist_view to render the page
return super().changelist_view(request, extra_context=extra_context)
def has_add_permission(self, request):
# Nobody is allowed to add
return False
def has_delete_permission(self, request, obj=None):
# nobody is allowed to delete
return False
# suit_classes = 'suit-tab suit-tab-faults'
empty_value_display = ''
list_filter = ('fault_type',)
search_fields = ('position',)
changelist_view html (admin override file)
<!--# machines/templates/admin/machines/machinefault/change_list.html-->
{% extends "admin/change_list.html" %}
{% load static %}
<!-- Override extrahead to add Chart.js -->
{% block extrahead %}
{{ block.super }}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const ctx = document.getElementById('myChart').getContext('2d');
// Sample data
const chartData = {{ chart_data | safe }};
// Parse the dates to JS
chartData.forEach((d) => {
d.x = new Date(d.date);
});
// Render the chart
const chart = new Chart(ctx, {
type: 'bar',
data: {
datasets: [
{
label: 'Breaks ',
data: chartData,
backgroundColor: 'rgba(220,20,20,0.5)',
},
],
},
options: {
responsive: true,
scales: {
xAxes: [
{
type: 'time',
time: {
unit: 'day',
round: 'day',
displayFormats: {
day: 'MMM D',
},
},
},
],
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
});
</script>
{% endblock %}
{% block content %}
<!-- Render our chart -->
<div style="width: 80%;">
<canvas style="margin-bottom: 5px; width: 50%; height: 15%;" id="myChart"></canvas>
</div>
<button id="reload" style="margin: 1rem 0">Reload chart data</button>
<!-- Render the rest of the ChangeList view -->
{{ block.super }}
{% endblock %}
But my chart is still blank - I have no errors.
Using latest Django, Python3.7
UPDATE: 2/14/2020
Can't be sure that this is the cause of your issue without seeing the HTML, but the way you are passing data to your chart JS is unsafe - don't do this:
const chartData = {{ chart_data | safe }};
It's very likely you are ending up with invalid JS as a result of this, because the output is not properly escaped. Instead, use the json_script filter to safely render your object, and then read this in JS. Something like this:
{{ chart_data|json_script:"chart-data" }}
<script>
const chartData = JSON.parse(document.getElementById("chart-data").textContent);
// initialise the chart as you currently do
</script>
Note - you need to stop encoding the data as JSON in your view - just pass it the original list which this filter will encode safely for you.
If this doesn't fix it then it's likely that the data structure itself is not what the chart library is expecting - perhaps if you post a sample of what chartData looks like we can see whether that looks right.

Chart JS Manual Bar Chart YAxis

I am working on a project that will use ratings from 1-10. The automatic scaling in ChartJs is causing issues where data is not displayed due to it not being in range.
How can I remove the automatic scaling of a bar chart yxais and manually set the scales to 1-10 ?
<canvas id="bar-chart-grouped" width="800" height="350"></canvas>
<script>
new Chart(document.getElementById("bar-chart-grouped"), {
type: 'bar',
data: {
labels: [{% for result in results %}
"{{result.title}}",
{% endfor %}],
datasets: [
{
label: "Rating",
backgroundColor: "#3e95cd",
data: [{% for result in results %}
"{{result.w_average}}",
{% endfor %}]
}, {
label: "My Rating",
backgroundColor: "#3cba9f",
data: [{% for result in results %}
"{{result.rating}}",
{% endfor %}]
}
]
},
options: {
title: {
display: true,
text: 'Movie Ratings'
}
}
});
</script>

Does Making an AJAX call make a DJANGO form Invalid?

I make an ajax call to my server using the change event on a select widget. Does this cause the Django Form to be invalid? Here is an example of the code.
JAVASCRIPT
<form class="form-horizontal" action="{% url 'accountSelections' %}" method="post">
{% csrf_token %}
<div class="form-group">
<div class="row">
<div class="col-md-4">
{{ account_selection_form|crispy }}
<input class="btn btn-primary" id="button" type="Submit" value="Next >>">
</div>
<div class="col-md-4">
</div>
<div class="col-md-4">
<div id="grid"></div>
</div>
</div>
</div>
</form>`
$( document ).ready(function() {
$("#id_excludeClassification").SumoSelect();
var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
$( "#id_acctFilterName" ).change(function() {
var data = "";
$.ajax({
type:"GET",
url : "../filter",
data : "id="+$(this).val(),
csrfmiddlewaretoken: token,
success : function(response) {
$("#grid").kendoGrid({
data: response,
height: 550,
groupable: true,
sortable: true,
columns: [
{
field: "acctCd",
title: "Code"
}, {
field: "shortName",
title: "Account Name"
}]
});
var grid = $("#grid").data("kendoGrid");
dataSource = new kendo.data.DataSource({
data: response
});
grid.dataSource = dataSource;
dataSource.read();
grid.refresh();
data = response;
return response;
},
error: function() {
alert('Error occured');
}
});
});
});
Does a form submit after cause this to make the form invalid?
My understanding is that you can submit multiple times with the same CSRF token, so it shouldn't be a problem.
you put your csrfmiddlewaretoken variable out data object that you send to your server then it can't work.
Here is what you have to do :
data : {
id : $(this).val(),
csrfmiddlewaretoken: token,
}

Serving Static Pages ember.js

I'm currently retrofitting an old site and added ember. Previously when the user went products > product there was a link to a static page from there.
What's the best way to route to these static pages? (sellsheet in the object)
{
id: 32,
room: "String",
subroom: "String",
category: "String",
image: "Content/Images/Products/img.PNG",
name: "String",
description: "String",
bullets: [
{ content: "String" },
{ content: "String" },
{ content: "String" }
],
sellsheet: "Content/Sellsheets/conveyor.html"
}
I know this isn't the best way of doing it but it fit my needs.
I ended up just displaying the static page in an iframe at the bottom of the product page. Whenever you click view more, I hide the page with jQuery then show the iframe which gets the html loaded in through the anchor tag. Then I added a 'view less button' that hides the iframe and shows the page again.
HTML
<script type="text/x-handlebars" id="product">
<div id="valueprop-container">
<div class="centered">
<div class="col-left"><img {{bind-attr src=image}} /></div>
<div class="col-right">
<h2>{{{name}}}</h2>
<p>{{{description}}}</p>
<ul>
{{#each bullets}}
<li><span>{{{content}}}</span></li>
{{/each}}
</ul>
{{#if sellsheet}}
View More
{{/if}}
</div>
</div>
</div>
<div class="shadow"></div>
<div class="sellsheet">
<button class="expand">View Less</button>
<iframe name="frame" width="100%" height="100%" allowfullscreen style="position: absolute; border: none;"></iframe>
</div>
</script>
View
App.ProductView = Ember.View.extend({
didInsertElement: function(){
var productPage = $('#valueprop-container');
var sellSheet = $('.sellsheet');
$('.sell-sheet-click').click('on', function(){
productPage.hide();
sellSheet.show();
});
$('.sellsheet').click('on', function(){
productPage.show();
sellSheet.hide();
});
}
});