3

I am using Python Django to create an interactive Dashboard. The main reason why I decided to use Django is because I can create users and groups to give different access to different people. Thought this was the better way.

I have massive reports built on excel sheets that I can convert to .CSV and machine readable. I read the best way to load data to D3 is through d3.csv(). I've tried that without success and now have tried with d3.json() but still I have used another code sample to try and plot my own but could have any luck.

The code is as follows. Important note: In dashboard.html, there is a selector, thus the HTML Template has that extends the "dashboard" template.

# app/models.py
from django.db import models

class wrtes(models.Model):
    name = models.CharField(max_length=150)
    date = models.DateTimeField()
# app/urls.py

from django.conf.urls import url
from . import views
from .views import graph, oneModel


urlpatterns = [

    # Dashboard parts
    url(r'^oneModel/', graph),
    url(r'^api/oneModel', oneModel, name='oneModel'),
]
# app/views.py
def graph(request):
    return render(request, 'app/oneModel.html')

def oneModel(request):
    data = oneModel.objects.all() \
        .extra(select={'month': connections[oneModel.objects.db].ops.date.trunc_sql('month', 'date')}) \
        .values('month') \
        .annotate(count_items=Count('id'))
    return JsonResponse(list(data), safe=False)
<!-- app/oneModel.html -->
{% extends 'app/dashboard.html' %}
{% load staticfiles %}

{% block content %}

<script src="https://d3js.org/d3.v3.js"></script>       <!-- D3 obligatory tags -->
<script> 
var margin = {top: 20, right: 20, bottom: 30, left: 50},
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var parseDate = d3.time.format("%Y-%m-%d").parse; // for dates like "2014-01-01"
//var parseDate = d3.time.format("%Y-%m-%dT00:00:00Z").parse;  // for dates like "2014-01-01T00:00:00Z"

var x = d3.time.scale()
    .range([0, width]);

var y = d3.scale.linear()
    .range([height, 0]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom");

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");

var line = d3.svg.line()
    .x(function(d) { return x(d.month); })
    .y(function(d) { return y(d.count_items); });

var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.json("{% url "oneModel" %}", function(error, data) {
  data.forEach(function(d) {
    d.month = parseDate(d.month);
    d.count_items = +d.count_items;
  });

  x.domain(d3.extent(data, function(d) { return d.month; }));
  y.domain(d3.extent(data, function(d) { return d.count_items; }));

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Play count");

  svg.append("path")
      .datum(data)
      .attr("class", "line")
      .attr("d", line);
});

</script>

{% endblock %}

When running the local server, it does not render anything in the graphics part. It renders the remaining parts - navbar, selector & so on. It makes me consider the dataset is not being loaded in any way. This one in particular, does not even make sense :-D But when I tried with the d3.csv() method, it was not working either way.

  • What is wrong with the code?
  • What is the best way to pass .csv files to D3 to plot cute stuff? If you'll be referencing guides, please consider I am not a programmer nor a very experienced one.

Thank you for your time.

Gustavo Silva
  • 159
  • 1
  • 12
  • In your `oneModel(request)` (which is where your data is coming from) you don't return anything. Further, even if you returned `data` it's going to be some sort of Python object. You need to serialize it to JSON and then consume it with `d3.json`... – Mark Oct 10 '16 at 15:28
  • Thanks for replying. My code was mainly inspired by [this](http://stackoverflow.com/questions/26453916/passing-data-from-django-to-d3) guide. It works there apparently... How can I do that in my model then? – Gustavo Silva Oct 10 '16 at 15:42
  • Yes, but in that answer they are doing like I suggest: `return JsonResponse(list(data), safe=False)` and then using `d3.json`. I don't see that in your code above... – Mark Oct 10 '16 at 15:45
  • You're right. Tested with that line in `views.py` and still nothing. – Gustavo Silva Oct 10 '16 at 15:50
  • At a glance, your code looks right now, so you'll need to do some basic troubleshooting. Does your browser ever call `d3.json("{% url "oneModel" %}"`? If so, does Python return the JSON correctly? Do you see any errors in the browser console? – Mark Oct 10 '16 at 16:01
  • In the console, I have this: `Uncaught TypeError: Cannot read property 'format' of undefined` And looking at the error specifically, it went to: `var parseDate = d3.time.format("%Y-%m-%d").parse;` – Gustavo Silva Oct 10 '16 at 16:06
  • Ahh, I missed that, you are loading d3 version **4**. The code sample you are following is d3 version **3**. Change `` to ``. – Mark Oct 10 '16 at 16:13
  • And then I got two more errors... :P `GET http://localhost:8000/dashboard/api/wrtes 500 (Internal Server Error)` and `Uncaught TypeError: Cannot read property 'forEach' of undefined` – Gustavo Silva Oct 10 '16 at 16:19

0 Answers0