NVD3 Chart won't render in Django - django

I'm having trouble getting my nvd3 pie chart to render.
I'm using a template tag (simple tag) to return the data required to construct the pie chart.
Already verified:
All static files are loading
The template tag is passing the correct dictionary to the template
All templates are loading
No errors
The chart appears to be loading in the source code header
color-id.html (template for just the pie chart)
{% load static %}
<link media="all" href="{% static 'nvd3/build/nv.d3.css' %}" type="text/css" rel="stylesheet" />
<script type="text/javascript" src='{% static 'd3/d3.min.js' %}'></script>
<script type="text/javascript" src='{% static 'nvd3/build/nv.d3.min.js' %}'></script>
{% load nvd3_tags %}
{% load basic_deck_stats %}
<head>
{% include_chart_jscss %}
{% color_id deck as data %}
{% load_chart data.charttype data.chartdata data.chartcontainer data.extra %}
</head>
<body>
<h3>Color Identity</h3>
{% include_container "asdf" 400 400 %}
charttype: {{ data.charttype }}<br>
chartdata: {{ data.chartdata }}<br>
chartcontainer: {{ data.chartcontainer }}<br>
extra: {{ data.extra }}
</body>
basic_deck_stats.py (template tag)
from django import template
from card_search.views import Card, Deck, Quantity
from django.shortcuts import render_to_response
register = template.Library()
#register.simple_tag
def color_id(deck):
black=blue=red=white=green = 0
queryset = Quantity.objects.filter(deck__deck_name=deck.deck_name).all()
for item in queryset:
if item.card.mana_cost:
black += item.card.mana_cost.count("{B}") * item.qty
blue += item.card.mana_cost.count("{U}") * item.qty
red += item.card.mana_cost.count("{R}") * item.qty
white += item.card.mana_cost.count("{W}") * item.qty
green += item.card.mana_cost.count("{G}") * item.qty
xdata = ["Black", "Blue", "Red", "White", "Green"]
ydata = [black, blue, red, white, green]
chartdata = {'x': xdata, 'y': ydata}
charttype = 'pieChart'
chartcontainer ='piechart_container'
data = {
'charttype': charttype,
'chartdata': chartdata,
'chartcontainer': chartcontainer,
'extra': {
'x_is_date': False,
'x_axis_format': '',
'tag_script_js': True,
'jquery_on_ready': False,
}
}
return data
Then I'm calling the pie chart template from the deck.html template
{% include "../charts/color-id.html" %}
Hope that's enough detail.
Any help would be much appreciated!
Alex

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 %}
]
}

How to place Bokeh widgets precisely on an html page

I am struggling to place Bokeh widgets precisely where I want them on an html page built with Django. For example my views.py look like this:
from bokeh.io import show
from bokeh.layouts import column, row
from bokeh.models import CustomJS, TextInput
from bokeh.plotting import figure
fig = figure(title='title')
fig.line(x=[1,2,3], y=[1,2,3])
text_input = TextInput(title="Add graph title", value='')
text_input.js_on_change('value', CustomJS(
args={'title': fig.title, 'text_input': text_input},
code="title.text = text_input.value"
))
widgets_layout = column(text_input)
figures_layout = row(fig)
#show(row(widgets_layout, fig))
# Set up page layout
page_layout = row(widgets_layout, figures_layout)
script, div = components(page_layout)
return render_to_response('app/test.html', {'script':script, 'div':div})
and my html page (test.html) look like this:
<!--Test page-->
{% extends "base.html" %}
{% load static %}
{% load bootstrap4 %}
{% load i18n %}
{% block content %}
<!--Bokeh-->
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.css" rel="stylesheet" type="text/css">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.css" rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.3.4.min.js"></script>
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-tables-1.3.4.min.js"></script>
<!--Figure-->
<div class='col-lg'>
<div class='card-lg bg-light' id='maincontent'>
<h2> {% trans "Test" %}</h2>
<hr>
<div>
{{ div | safe }}
{{ script | safe }}
</div>
</div>
</div>
<br>
{% endblock content %}
Now, how can I move the little widget (text_input) to a precise position ? Any position will do, I just want to be able to place it pretty much wherever I want.
Thank you,
You could apply for example spacing (which can also be negative) on the Row and/or on the Column like this:
widgets_layout = column(Div(), row(Div(), text_input, spacing=300), spacing=300)

Django - Show plot from SQLite database, accessed by form

So I have a page written using Django where someone can enter information into a form, and on submit it accesses a SQLite database to retrieve the queried information. So far I have gotten this far, but I am not able to create and show a plot below the form on the page.
I have tried different packages: ChartIt, Graphos and nvd3. Either way I get an error, likely because I don't understand the full details of the coding in Django.
Below is my try at creating a plot with nvd3. When I try to load the page I get the error:
Exception Value: Invalid block tag: 'load_chart', expected 'elif', 'else' or 'endif'
at the line in my viewrun.html where I assume I load in the nvd3:
{% load_chart charttype chartdata "linewithfocuschart_container" True "%d %b %Y %H" %}
Here are the files I use. Thank you for any help!
views.py
def createplot(molecules, chemrun_id, database='laminar_idl.test.db'):
conn, status_db = conn_to_db(database)
if status_db and not molecules==None:
time, x, y, abunds, status_fetch = get_one_species_all_times(conn, str(molecules))
chartdata = {'x': time,
'name1': molecules, 'y1': abunds}
charttype = "lineWithFocusChart"
data = {
'charttype': charttype,
'chartdata': chartdata
}
return data
return None
#login_required
def run(request, chemrun_id=1, molecule=None):
if request.POST:
form = MolChoiceForm(request.POST)
if form.is_valid():
form.save()
molecule = form.cleaned_data['molecule']
return HttpResponseRedirect('/chemrun/run/'+chemrun_id+'/'+molecule+'/')
else:
form = MolChoiceForm()
args = {}
args.update(csrf(request))
args['form'] = form
args['chemrun'] = ChemRun.objects.get(id=chemrun_id)
if not molecule is None:
args['molecule'] = molecule
plotdata = createplot(molecule, chemrun_id)
args['plotdata'] = plotdata
return render_to_response('interface/viewrun.html', args, context_instance=RequestContext(request))
viewrun.html:
{% extends "interface/base.html" %}
{% block content %}
<article>
{% if user.is_authenticated %}
<header>
<p><font size="+2">Chemical run: <i>{{run.title}}</i> (<b>ID #{{chemrun.id}}</b>)</font></p>
{% load_chart charttype chartdata "linewithfocuschart_container" True "%d %b %Y %H" %}
</header>
<section>
<p>Outputs written for {{chemrun.n_times}} time steps between {{chemrun.times_min}} and {{chemrun.times_max}} years</p>
<p>Temperature: <b>{{chemrun.temperature}}</p>
<p>Density: <b>{{chemrun.density}}</p>
<hr>
<form action='/chemrun/run/{{chemrun.id}}/' method='post' style="display: inline-block;">{% csrf_token %}
{{form}}
<input type="submit" name="submit" value="Plot">
</form>
</section>
{% else %}
<h2>No data available because you are not logged in.
{% endif %}
{% endblock %}
base.html:
{% load staticfiles %}
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="apple-touch-icon" href="apple-touch-icon.png">
<link rel="stylesheet" href="{% static 'css/normalize.min.css' %}">
<link rel="stylesheet" href="{% static 'css/main.css' %}">
<link media="all" href="{% static 'nvd3/src/nv.d3.css' %}" type="text/css" rel="stylesheet" />
<script type="text/javascript" src='{% static 'd3/d3.min.js' %}'></script>
<script type="text/javascript" src='{% static 'nvd3/nv.d3.min.js' %}'></script>
<!--<script src="js/vendor/modernizr-2.8.3-respond-1.4.2.min.js"></script>-->
<title>Chemicalizer</title>
</head>
<body>
<div class="header-container">
<header class="wrapper clearfix">
<h1 class="title"><b><a href='/'>Chemicalizer</a></b> </h1>
<!--<h2 class="subtitle">- You need it!</h2>-->
<nav>
<ul>
{% if user.is_authenticated %}
{% if user.is_superuser %}
<li>Admin</li>
<li>All Models</li>
{% else %}
<li>Start model</li>
<li>My Models</li>
{% endif %}
<li>Logout</li>
{% else %}
<li>Login</li>
<li>Register</li>
<li>Contact</li>
{% endif %}
</ul>
</nav>
</header>
</div>
<div class="main-container">
<div class="main wrapper clearfix">
{% block content %}
{% endblock %}
</div> <!-- #main -->
</div> <!-- #main-container -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.11.2.min.js"><\/script>')</script>
<!--<script src="js/main.js"></script>-->
</body>
</html>
For people in the future fighting the same problem, I was using pages that did not explain all steps for getting nvd3 to work (or they were maybe outdated).
Here are the steps to follow to install it and get it working:
1) Install django-nvd3 using pip install django-nvd3
2) Since this is dependent on python-nvd3, we need to install bower using npm install -g bower. (If you don't have npm, just install it with macports, or any other way you like.)
3) Next, install django-bower with the command pip install django-bower
4) Then run bower install nvd3 which will also install the dependency d3
5) Edit your view.py to something like this, this example is for a lineChart:
charttype = "lineChart"
chartcontainer = 'linechart_container' # container name
data = {
'charttype': charttype,
'chartdata': chartdata,
'chartcontainer': chartcontainer,
'extra': {
'x_is_date': False,
'x_axis_format': '',
'tag_script_js': True,
'jquery_on_ready': True,
'chart_attr': {
'xScale':'(d3.scale.log())', #for logscale on x-axis
'yScale':'(d3.scale.log())', #for logscale on y-axis
'xAxis.axisLabel':'"Time, yrs"',
'yAxis.axisLabel':'"n(X)/n(H)"',
}
}
}
return data
6) Update your settings.py with the following:
BOWER_COMPONENTS_ROOT = BASE_DIR
BOWER_PATH = '/usr/local/bin/bower'
BOWER_INSTALLED_APPS = (
'd3',
'nvd3',
)
and also add 'djangobower.finders.BowerFinder', to your STATICFILES_FINDERS = (
7) Now your html code has to include these (in the head for example):
<link media="all" href="{% static 'nvd3/src/nv.d3.css' %}" type="text/css" rel="stylesheet" />
<script type="text/javascript" src='{% static 'd3/d3.min.js' %}'></script>
<script type="text/javascript" src='{% static 'nvd3/nv.d3.min.js' %}'></script>
And somewhere in your main body:
{% include_chart_jscss %}
{% load_chart charttype chartdata chartcontainer extra %}
Finally, for wherever you want the plot to appear:
{% include_container chartcontainer %}
This worked for me. If anyone more knowledgeable about this finds any mistakes, please help me correct them :)

Google maps not being displayed in django template

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

Django TinyMCE issues

All the textareas are inline, StackedInline
All textareas works fine in this model change_view. BUT, when I add a new row the last row is not editiable in the textarea.
If I remove the mode:"textareas" in the tunyMCE Init, it abviasly removes the wsgi editor but then the textareas work when adding new ones. So I guess its tinyMCE that breaks it.
But I haved copied this tinyMCE files form another project where it works. So I dont know wtf!
I have my tinymce setup like this:
media/js/tinymce
then I have in templates:
templates/admin/app_name/model_name/change_form.html
and this is my change_form.html
{% extends "admin/change_form.html" %}
{% load i18n %}
{% block extrahead %}{{ block.super }}
{% url 'admin:jsi18n' as jsi18nurl %}
<script type="text/javascript" src="{{ jsi18nurl|default:"../../../jsi18n/" }}"></script>
{{ media }}
<script type="text/javascript" src="{{ MEDIA_URL }}js/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="{{ MEDIA_URL }}js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript">
function CustomFileBrowser(field_name, url, type, win) {
var cmsURL = "/admin/filebrowser/browse/?pop=2";
cmsURL = cmsURL + "&type=" + type;
tinyMCE.activeEditor.windowManager.open({
file: cmsURL,
width: 850, // Your dimensions may differ - toy around with them!
height: 650,
resizable: "yes",
scrollbars: "yes",
inline: "no", // This parameter only has an effect if you use the inlinepopups plugin!
close_previous: "no",
}, {
window: win,
input: field_name,
editor_id: tinyMCE.selectedInstance.editorId,
});
return false;
};
tinyMCE.init({
// add these two lines for absolute urls
remove_script_host : false,
convert_urls : false,
// General options
mode : "textareas",
theme : "advanced",
plugins : "safari,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media",
file_browser_callback: 'CustomFileBrowser',
// Theme options
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|styleselect,formatselect,|,undo,redo,|,link,unlink,image,code",
theme_advanced_buttons3 : "",
theme_advanced_buttons4 : "",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
// theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : false,
width:300,
height:300,
});
</script>
{% endblock %}
{% block object-tools %}
{% if change %}{% if not is_popup %}
<ul class="object-tools">
<li>{% trans "History" %}</li>
{% if has_absolute_url %}
<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/" class="viewsitelink">
{% trans "View on site" %}</a>
</li>
<li><a href="../../../r/{{ content_type_id }}/{{ object_id }}/html/" class="viewsitelink">
{% trans "View source" %}</a>
</li>
{% endif%}
</ul>
{% endif %}{% endif %}
{% endblock %}
Even If I do this in textareas.js and include that in the chnage_form.html extrahead block it does the same.
Well, I figured out what was wrong. Maybee someone runs into the same problem
The problem is thart when adding a new row, that texarea is not initiated by tinymce, bacause it only does that once, when the pages loads. Makses perfect sence, so you need to add functionality to the textarea again after adding anew row.
This is how I did it:
change_form.html, added this to the bottom of the file
$(".add-row a").click(function () {
// this is the span that the current wsgi editor is in, so I remove it
$($(this).parent().prev().prev().find("span")[2]s).remove();
// Now I display the original textarea
$(this).parent().prev().prev().find("textarea").show();
// and Finaly lets add MCE control to this area.
tinyMCE.execCommand(
'mceAddControl',
false,
$(this).parent().prev().prev().find("textarea").attr('id')
);
});