I have been trying to send a Python Dictionary to a HTML Page and use that dictionary in Javascript to add a Graph on my website, using Django
The form takes a Image Upload, and the code is as follows,
<div class=" mx-5 font-weight-bold">
Uplaod Image
</div>
<input class=" " type="file" name="filePath">
<input type="submit" class="btn btn-success" value="Submit">
This image is then sent to views.py where it is processed and a resultant image, as well as a dictionary is generated from that image. And then again, a HTML page is rendered where the dictionary as well as the resultant image is sent in context variable. The code is as follows,
def predictImage(request):
fileObj = request.FILES['filePath']
fs = FileSystemStorage()
filePathName = fs.save(fileObj.name, fileObj)
filePathName = fs.url(filePathName)
testimage = '.'+filePathName
img_result, resultant_array, total_objects = detect_image(testimage)
cv2.imwrite("media/results/" + fileObj.name, img=img_result)
context = {'filePathName':"media/results/"+fileObj.name, 'predictedLabel': dict(resultant_array), 'total_objects': total_objects}
#context = {}
return render(request, 'index.html', context)
Now, I want to convert the Dictionary items and keys into two different Javascript arrays, which are then to be used to plot a Graph on the HTML page. The template code of the Javascript is as follows,
<script>
// const value = JSON.parse(document.getElementById('data_values').textContent);
// alert(value);
var xArray = [];
var yArray = [];
var xArray = ["Italy", "France", "Spain", "USA", "Argentina"]; // xArray needs to have Python Dictionary's keys
var yArray = [55, 49, 44, 24, 15]; // yArray needs to have Python Dictionary's values
var layout = { title: "Distribution of Labels" };
var data = [{ labels: xArray, values: yArray, hole: .5, type: "pie" }];
Plotly.newPlot("myPlot", data, layout);
</script>
I have tried a lot of different things to access my Python Dictionary in the Javascript Script and then convert that to Javascript arrays, but I still have not managed to do it. I also tried different Stackoverflow posts etc but nothing could really properly guide me on this. I am quite new to Django as well so I am not much aware of the syntax as well.
From Django-doc json_script
{{ value|json_script:"hello-data" }}
inside your Javascript
<script>
const data = JSON.parse(document.getElementById('hello-data').textContent);
var xArray = Object.keys(data) // return list of keys
var yArray = Object.values(data) // return list of values
</script>
can you take a try this,
views.py
# context data
context = {'filePathName':"media/results/"+fileObj.name, 'predictedLabel': dict(resultant_array), 'total_objects': total_objects,
"data": {"Italy":11, "France":22, "Spain":22, "USA":23, "Argentina":12}}
template.html
<script>
// const data = JSON.parse();
// alert(value);
var data = JSON.parse("{{data|safe}}".replaceAll("'", '"'));
var xArray = [];
var yArray = [];
var xArray = Object.keys(data); // xArray needs to have Python Dictionary's keys
var yArray = Object.values(data) // yArray needs to have Python Dictionary's values
var layout = { title: "Distribution of Labels" };
var data = [{ labels: xArray, values: yArray, hole: .5, type: "pie" }];
Plotly.newPlot("myPlot", data, layout);
</script>
html
<input type="hidden" id="dictionary" value="{{ dictionary }}" />
JS
var dictionary = JSON.parse($('#dictionary').val());
If I have a simple Python time data series like this:
graphdata = []
graphdata.append( [(datetime.date(2008, 5, 7)),75])
graphdata.append([(datetime.date(2008, 5, 8)), 85])
graphdata.append([(datetime.date(2008, 5, 10)), 60])
How can I pass the data to a Flask page running Dygraph?
Do I need to use GViz?
Any examples would be helpful.
Thanks
Bill
No need to pass the data as a list containing datetime objects. Dygraphs reads CSV format with ease. So just pass the data as one long CSV string. For your case, first formulate that string containing your data:
graphdata = ''
graphdata = graphdata + '2008-05-07, 75\n'
graphdata = graphdata + '2008-05-08, 85\n'
graphdata = graphdata + '2008-05-10, 60\n'
Now, let's say this you wish to render this data on your index page, then do this in your views.py:
#app.route('/')
def index():
return render_template('index.html',graphdata)
Finally, this data is received by your index.html and rendered using the following code:
<div id="graphdiv"></div>
<script type="text/javascript">
g = new Dygraph(
// containing div
document.getElementById("graphdiv"),
// CSV or path to a CSV file.
{{ graphdata }}
);
</script>
Make sure that dygraph.js is included in your Flask app.
I am trying to print in console.log() my series variable but no success so far.
def multiple_series(res):
matrix = dict(res)
all_cat_keys = set(key[0] for key in matrix)
categories = sorted(all_cat_keys)
all_series_keys = set(key[1] for key in matrix)
series = [
{
'name': series_key,
'data': [
[cat_key, matrix.get((cat_key, series_key), 0)]
for cat_key in categories
],
}
for series_key in all_series_keys
]
return series
I've tried using json.dumps() and the well known console.log({{ series }}) but I get nothing.
I'd like to print the content of name and data. Can anyone help me ? I don't have much experience using JS. Thanks
console.log({{ series }}) can not work because {{ series }} gets evaluated to text. Therefore JS thinks it's a JS object.
Add quotes around the object to treat it as text and it should work:
console.log("{{ series }}");
Iam not sure about your input data - but you are building the series list the wrong way. You should build you series list like that:
def multiple_series(res):
matrix = dict(res)
all_cat_keys = set(key[0] for key in matrix)
categories = sorted(all_cat_keys)
all_series_keys = set(key[1] for key in matrix)
series = []
for series_key in all_series_keys:
dict_to_add = {'name': series_key}
data_information = []
for cat_key in categories:
data_information.append((cat_key, matrix.get((cat_key, series_key), 0)))
dict_to_add['data'] = data_information
series.append(dict_to_add)
return series
I am using Django with the Google Charts API. I need to construct a JavaScript array to render a bar chart showing the # of objects created in a given day.
The expected array printed to the template should look like:
...
function drawStuff() {
var data = new google.visualization.arrayToDataTable([
['Date', '# of records'],
['2015-03-07', 3], // Expected format: ['Date', # of objects]
['2015-03-08', 8],
]);
...
views.py:
class LogsView(TemplateView):
template_name = 'logs.html'
def ValuesQuerySetToDict(self, vqs):
return [ [item['date_created'], item['created_count'] ] for item in vqs]
def render_chart_data(self, **kwargs):
queryset = LogEntry.objects.filter(user=self.request.user).extra(
{'date_created': 'date(created)'}
).values('date_created').annotate(created_count=Count('id'))
modified_dict = self.ValuesQuerySetToDict(queryset)
return json.dumps(modified_dict)
def get_context_data(self, **kwargs):
context = super(
LogsView, self
).get_context_data(**kwargs)
context['chart_data'] = self.render_chart_data()
The following is rendered to my django template (I bypassed sending it to JavaScript for now to see what was returned...
When I believe I need to return a JavaScript array like the following:
["2015-02-18", 3],
["2015-02-19", 12],
["2015-02-21", 1],
And feed that to the drawStuff function which will render the barchart.
Alternate Method
I followed the this thread on StackOverflow and modified the render_chart_data to use django serializer like this but I am getting an error: " 'dict' object has no attribute '_meta'
Thanks to all who offered assistance on this.
Two things needed to changed; the ValuesQuerySetToDict function needed to be rewritten as follows:
def ValuesQuerySetToDict(self, vqs):
list_vals = [ ['Date', '# of records'] ]
for item in vqs:
list_vals.append(
# convert datetime object to string otherwise JSON serialization error
[ str(item['date_created']), item['created_count'] ]
)
return list_vals
And the render_chart_data function needed to be rewritten as follows:
def render_chart_data(self, **kwargs):
queryset = LogEntry.objects.filter(user=self.request.user).extra(
{'date_created': 'date(created)'}
).values('date_created').annotate(created_count=Count('id')).order_by('created-date')
modified_list = list(self.ValuesQuerySetToDict(queryset))
json_data = json.dumps(modified_list)
return json_data
Finally, {{ chart_data }} needed to be passed to to the drawStuff function, like so:
function drawStuff() {
var data = new google.visualization.arrayToDataTable(
{{ chart_data|safe }}
);
I've posted views.py and logs.html here.
In your queryset, render created_count as string and not as integer. Json's do not behave well with Integers.
In your JS function drawStuff, chart_data should be parsed as json. See below:
var json_string = '{{chart_data}}';
var json = JSON.parse(json_string);
var data = new google.visualization.arrayToDataTable(json)
I currently have a PHP file which returns:
[[38,38],[38,113],[38,188],[38,263],[38,338],[38,413],[38,488],[113,38],[113,113],[113,188],[113,263],[113,338],[113,413],[113,488],[188,38],[188,113],[188,188],[188,263],[188,338],[188,413],[188,488],[263,38],[263,113],[263,188],[263,263],[263,338],[263,413],[263,488],[338,38],[338,113],[338,188],[338,263],[338,338],[338,413],[338,488],[413,38],[413,113],[413,188],[413,263],[413,338],[413,413],[413,488],[488,38],[488,113],[488,188],[488,263],[488,338],[488,413],[488,488],[75,75],[75,150],[75,225],[75,300],[75,375],[75,450],[150,75],[150,150],[150,225],[150,300],[150,375],[150,450],[225,75],[225,150],[225,225],[225,300],[225,375],[225,450],[300,75],[300,150],[300,225],[300,300],[300,375],[300,450],[375,75],[375,150],[375,225],[375,300],[375,375],[375,450],[450,75],[450,150],[450,225],[450,300],[450,375],[450,450]]
I use this in an AJAX call like
$.ajax({
url:'fetcher/allseedpositions.php',
async: false,
success:function(datasets){
seedPos = jQuery.parseJSON(datasets);
allNodePos = $.plot($("#allnodepositions"),[ seedPos ],optionsSeed);
}
})
to plot but now I want another series to be plotted also along with this, with different symbol.
I am confused on using JSON and I cannot add more properties.
You should be able to create a new array and push the next data set for display. http://jsfiddle.net/fZbVL/
var dataSet1 = [
[1,5],[4,7]
];
var dataSet2 = [
[1,2],[3,4]
];
var dataSet3 = [
[1,4],[4,6]
]
var data = []
data.push(dataSet1);
data.push(dataSet2);
data.push(dataSet3);
$.plot($("#placeholder"),
data);