Reputation: 1005
even though I have seen a lot of resource about similar topics, nothing has been able to solve my issue. the closest were How do I JSON serialize a Python dictionary? and django model serialization.
I am trying to plot a graph from a model on my frontend with Chart.js and I cannot get my view to be serialized and being able to fit the arguments for the graph. I attach my model.py, view.py and htlm page as well as the error that I get.
models.py
class Classification(models.Model):
Class = models.CharField(max_length=10, primary_key=True)
inventory_dollars = models.FloatField(default=0)
def __str__(self):
return self.Class
class ClassificationSerializer(serializers.ModelSerializer):
class Meta:
model = Classification
fields = "__all"
views.py
class HomeView(View):
def get(self, request, *args, **kwargs):
return render(request, 'dashboard/charts.html', {})
class ChartData(APIView):
authentification_classes = []
permission_classes = []
def get(self, request, format=None):
labels = Classification.Class
default_items = Classification.inventory_dollars
data = {
"labels" : labels,
"default": default_items
}
return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')
html
{% extends 'dashboard/base.html' %}
<script>
{% block jquery %}
var endpoint = '/api/chart/data'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function(data1){
labels = data1.labels
defaultData = data1.default
setChart()
},
error: function(error_data){
console.log(error_data)
}}
)
function setChart(){
var ctx = document.getElementById('myChart').getContext('2d');
var ctx2 = document.getElementById('myChart2').getContext('2d');
var mychart2 = new Chart(ctx2, {
type: 'polarArea',
data: {
labels: labels,
datasets: [{
label: '# of Votes',
data: defaultData,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}],
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
})
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: '# of Votes',
data: defaultData,
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(255, 206, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(255, 159, 64, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)',
'rgba(255, 206, 86, 1)',
'rgba(75, 192, 192, 1)',
'rgba(153, 102, 255, 1)',
'rgba(255, 159, 64, 1)'
],
borderWidth: 1
}],
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
}
})}
{% endblock %}
</script>
{% block content %}
<div class ='row'>
<div class="clo-sm-12">
<h1>Inventory Management Dashboard</h1>
<canvas id="myChart" width="400" height="100"></canvas>
<canvas id="myChart2" width="400" height="100"></canvas>
</div>
</div>
{% endblock content %}
As you can see i need to find a way to specify "labels" and "default" in my view in order to be plotted then in the html file. Here is the error that I get so far:
Request Method: GET
Request URL: http://127.0.0.1:8000/api/chart/data
Django Version: 3.0.4
Python Executable: /Users/pierre/Desktop/Django-app/bin/python
Python Version: 3.7.1
...
Traceback (most recent call last):
...
File "/Users/pierre/Desktop/inventory3/dashboard/views.py", line 67, in get
return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')
File "/Users/pierre/anaconda3/lib/python3.7/json/__init__.py", line 231, in dumps
return _default_encoder.encode(obj)
...
Exception Type: TypeError at /api/chart/data
Exception Value: Object of type Manager is not JSON serializable
Request information:
USER: AnonymousUser
GET: No GET data
POST: No POST data
FILES: No FILES data
how can I solve this? Thank you for any help
I am new to Django and I really don't know what to do no more.
update: thanks to @dirkgroten advice, i changed my view to this:
class ChartData(APIView):
authentification_classes = []
permission_classes = []
def get(self, request, format=None):
labels = Classification.objects.all().values_list('Class', flat=True)
default_items = Classification.objects.all().values_list('inventory_dollars', flat=True)
data = {
"labels" : labels,
"default": default_items
}
return HttpResponse(json.dumps(data), content_type = 'application/javascript; charset=utf8')
which now gives me the error:
TypeError: Object of type QuerySet is not JSON serializable
Upvotes: 1
Views: 564
Reputation: 20702
json.dumps()
will only accept a python list
or a python dict
. Also, inside the dict
and list
you can only use dict
, list
and the primitive python types str
, int
and float
.
So you can't just pass it just your model instances, unless you serialise them first (which is what your ClassificationSerializer
does). But in fact, it seems your graph API just want two lists of values, so you should fetch them using labels = Classification.objects.values_list('Class', flat=True)
.
Finally, this returns a QuerySet
(labels
), so you need to make it a list
first: list(labels)
.
Note: I would strongly advise you to rename your field Class
to something else with lowercase. Indeed you cannot call it class
because it's a reserved keyword, but attributes in python should be lowercase. Your naming is making for hard-to-read code.
Upvotes: 1