I have generated a variable data in Django with the following format:
data = [['100',10],['90',9],['80',8]]
and I've passed it off to my template using render_to_response:
return render_to_response('template.html', {
'data': data,
},
context_instance=RequestContext(request))
In the template header I have placed a call to Google Charts to generate a line chart:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load('visualization', '1.0', {'packages':['corechart']});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = new google.visualization.DataTable();
data.addColumn('string', 'Number');
data.addColumn('number', 'Number/10');
data.addRows( {{ data }} );
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, {width: 400, height: 240, title: "Numbers"});
}
</script>
When I do this, nothing is displayed. If I strip the strings out of data and try again, the chart appears, but obviously with no x-axis labels.
I have also tried adding the data using the arrayToDataTable function:
var data = google.visualization.arrayToDataTable([
['Number', 'Number/10'],
{% for datum in data %}
{{ datum }},
{% endfor %}],
false);
but this again fails to display any chart.
Any suggestions on how I can change one of the above, or try another approach to get the x-axis labels to appear?
You have to disable the autoescaping of your results. You can do so by adding the safe filter:
data.addRows( {{ data|safe }} );
or
{% autoescape off %}
[...]
{{ data }}
[...]
{% endautoescape %}
My advice is, if you can install additional packages, to use one of these wrappers:
http://code.google.com/p/google-chartwrapper/
https://github.com/jacobian/django-googlecharts/
I can't add more than two links yet but another one is located here: code.google.com/p/django-graphs/
Related
My question is I need to make a dashboard page. In that, I need to make a chart on day to day created objects by the specific user in Django like the image below.
Also, I need to know how to save data for this like charts.
There are lots of options if you want to create charts. Most of them are JS and/or Ajax which you can include in the template page. Try this Google Charts which I believe is the simplest way to get things up and running,
https://developers.google.com/chart/interactive/docs/gallery/piechart
You can use the parameters from the context dictionary to generate a dynamic graph.
1 From views.py Send the Value of the data (ie the number of Problems solved) through the context Dictionary.
ex: views.py
def index(request):
context = {"problems_solved" : calculated_value}
return render(request, "results.html", context)
in the Template HTML do the following ,
results.html:
{% extends "base.htm" %}
{% load static %}
{% block title %}
results
{% endblock %}
{% block head %}
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
var solved = {{problems_solved}};
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['day', 'problems solved'],
['prob solved', solved ]
]);
var options = {
title: 'Profile progress Report: '
};
var chart = new google.visualization.PieChart(document.getElementById('piechart'));
chart.draw(data, options);
}
</script>
{% endblock %}
{% block body %}
<div id="piechart" style="width: 600px; height: 500px;">
{% endblock %}
If you are looking it to be generated everyday dynamically then you need to append values based with date to the context dictionary and execute the form generation everytime the page gets loaded
What's the most elegant solution in Django to take data from database and pass it into Highcharts? I stumbled across this question, but I keep on getting the following error: JSerror: Invalid property id at var chart_id = {{ chartID|safe }}, if I try to use it in my example.
template looks like this:
<html>
<div id={{ chartID|safe }} class="chart" style="height: 100px; width: 500px"></div>
<script>
var chart_id = {{ chartID|safe }}
var series = {{ series|safe }}
var title = {{ title|safe }}
var xAxis = {{ xAxis|safe }}
var yAxis = {{ yAxis|safe }}
var chart = {{ chart|safe }}
</script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
In case there are better ways to pass data to highcharts please let me know.
Maybe you are missing the quotes in your javascript:
var chart_id = "{{ chartID|safe }}";
You must pass your data as a context to the template, change it to a list in python. Then in your javascript block create a script tag then declare your data variables that you passed ,then pass them to your plotting script.
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.
I am trying to display a google map for a django site. I have a template, roughly,
{% extends "base.html" %}
{% load staticfiles %}
{% block content %}
...
<div class="col-md-6">
<div id="map_canvas" style="width:100%;height:400px;background-color:#CCC;"></div>
</div>
...
<script src="https://maps.googleapis.com/maps/api/js"></script>
<script>
function initialize() {
var mapCanvas = document.getElementById('map_canvas');
var mapOptions = {
center: new google.maps.LatLng(44.5403, -78.5463),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(map_canvas, map_options);
}
</script>
{% endblock%}
When I reload the webpage, I can see that a request is being made for Google's map url's , but I see no map, just a plain gray background.
i have the same problem in html code I delete <!DOCTYPE html> and it work
You just need to add the line before closing your script tag:
google.maps.event.addDomListener(window, 'load', initialize);
You can see it in the Documentation
I have this code I'm using to generate a list of records categorized into year, make, series, body style, and color for vehicles. I'd like to customize this further this way:
for the year, I want to have only up to 2004 being individual...the rest will fall under other i.e. 2009, 2008, 2007, 2006, 2005, 2004, Other.
for the make, I want to display the six makes with the highest popularity...there's a field in the model I'm using to assign the popularity of a make with a value of primary (highest), secondary or tertiary. The rest will fall under Other.
For the body style and color, I want to have the items having less than 3 records falling under Other.
My code is as below:
year_count = vehicle_query.order_by(
'-common_vehicle__year__year').values('common_vehicle__year__year').
annotate(count=Count('id'))
make_count = vehicle_query.order_by(
'common_vehicle__series__model__manufacturer__manufacturer').
values('common_vehicle__series__model__manufacturer__manufacturer').
annotate(count=Count('id'))
style_count = vehicle_query.order_by(
'common_vehicle__body_style__style').values
('common_vehicle__body_style__style').annotate(count=Count('id'))
colour_count = vehicle_query.order_by(
'exterior_colour__exterior_colour').values(
'exterior_colour__exterior_colour').annotate(count=Count('id'))
The bulk of what you're asking would probably better be handled outside of Django and instead by client-side javascript. To be clear, you could have portions handled by Django, but it would be cleaner not doing so. There are benefits to doing it this way:
Your Django template code stays cleaner
It will degrade nicely
You can later update the interface (change the javascript) and not have to worry about breaking the Django template
To handle this you could simply make a script that when given a <ul> tag (and maybe some arguments) will render that list in the format you're asking about.
Here's a simple example using jQuery. For this example, I'm going to wrap the functionality in a using a jQuery plugin pattern.
Say your django template outputs the following...
<ul>
<li>Chevy</li>
<li>Mazda</li>
<li>Honda</li>
<li>Ford</li>
<li>BMW</li>
</ul>
jquery.showmorelist.js
(function($) {
$.fn.ShowMoreList = function(visibleItemCount) {
// Wrap parent element
var parent = $(this).wrap('<div class="show-more-list"></div>').parent();
var ul = $(this);
// Enumerate children and hide extras
var counter = 0;
$(this).children().filter('li').each(function(){
counter += 1;
if (counter > visibleItemCount) {
$(this).hide();
$(this).addClass('hidden');
}
});
// Add link and bind click
var link = $('> Show More').click(function(){
$(ul).children().filter('.hidden').show();
});
$(parent).append(link);
}
})(jQuery);
page.html
<script type="text/javascript" src="jquery.showmorelist.js"></script>
<script type="text/javascript">
// On page load...
$(function() {
$('ul').ShowMoreList(4); // Shows only the first 4 items
});
</script>
This is a rather simple example, and it won't switch the "Show More" to "Hide More" but you should be able to figure that out from the context.
I managed to get a solution, so I thought it'd be good to update the answer here:
In the head section I have this:
<script type="text/javascript" src="{{ MEDIA_URL }}share/jquery/jquery.min.js"></SCRIPT>
<script type="text/javascript">
(function($) {
$(document).ready(function() {
//hide the additional content under "Display More"
$("div.additional_content").hide();
$("a.more").click(function () {
//show or hide the additional content
$(this).siblings("div.additional_content").toggle();
//change the attributes and text value of the link toggle
if($(this).text() == "Display Less"){
$(this).removeClass("less");
$(this).addClass("more");
$(this).html("Display More");
}else{
$(this).removeClass("more");
$(this).addClass("less");
$(this).html("Display Less");
}
return false;
});
});
})(jQuery);
Then wherever I want to reduce the number of available options I have this:
<div class="module_wrap">
<div class="module"> {% if year_count %} <strong>{% trans "Year" %}</strong> <br />
{% for item in year_count|slice:":6" %}
<ul>
<li> {{ item.common_vehicle__year__year }} ({{ item.count }}) {% if request.session.chosen_year %} <img src="{{ MEDIA_URL }}img/undo.gif" border="0" alt="Remove Year Filter" title="Remove Year Filter" /> {% endif %} </li>
</ul>
{% endfor %}
<div class="additional_content"> {% for item in year_count|slice:"6:" %}
<ul>
<li> {{ item.common_vehicle__year__year }} ({{ item.count }})</li>
</ul>
{% endfor %} </div>
{% if year_count|slice:"6:" %}Display More<br />
{% endif %} <br />
</div>
</div>
{% endif %}