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)
Related
I have PATCH button form on ModelViewSet
class CompanyViewSet(viewsets.ModelViewSet):
serializer_class = s.CompanySerializer
queryset = m.Company.objects.all()
def patch(self, request, id, format=None):
print(id)
Now I try to modify the existing data id = 1
So I write this in textarea and push PATCH button.
{
"id":1,
"name": ""
}
However , there comes error like
patch() missing 1 required positional argument: 'id'
Maybe my json is wrong?? How can I do PATCH?
patch() missing 1 required positional argument: 'id'
Use perform_update like this :
class CompanyViewSet(viewsets.ModelViewSet):
serializer_class = s.CompanySerializer
queryset = m.Company.objects.all()
def perform_update(self, serializer):
instance = serializer.instance
request = self.request
serializer.save(**modified_attrs)
return Response(status=status.HTTP_200_OK)
I am trying to create a chart Using Chartjs and Django,
i have a problem when i am trying to pass the data from views.py to js code.
so,this is my code in views.py..
def home(request):
labels = ["A", "B", "C", "D"]
data = [1,2,3,4]
return render(request, 'home.html',{'labels': labels
,'data': data,})
and this is my part of code in home.html ..
<script>
var labels = {{labels}};
var data = {{data}};
var ctx = document.getElementById('myChart').getContext('2d');
var chart = new Chart(ctx, {
// The type of chart we want to create
type: 'line',
// The data for our dataset
data: {
labels: labels,
datasets: [{
label:"chartLabel",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data:data,
}]
},
// Configuration options go here
options: {}
});
</script>
put when i use these tow lines in js ..
var labels = ["A", "B", "C", "D"];
var data = [1,2,3,4];
instead of this tow my code works fine.
var labels = {{labels}};
var data = {{data}};
and this is my page source
For a dict or list, best to use JSON, because that renders a Javascript data structure (the JS in JSON refers to Javascript)
import json
return render(request, 'home.html', {
'labels': json.dumps(labels),
'data': json.dumps(data)
})
Then in the Django template, the output of the json.dumps() call is a valid JS object.
var labels = {{labels}};
var data = {{data}};
You'll need to render your data as if it were a string so that the output is valid javascript that the browser can interpret:
var data = {{ str(data) }};
var labels = {{ str(labels) }};
The above expressions convert the array into a string representation of the array, so [1, 2, 3] would be rendered as '[1,2,3]' and ["a", "b", "c"] would be rendered as '["a","b","c"]'.
A quick way to check if this is working right would be to right click and view the page source, then scroll down to this javascript and verify that it looks like valid variable declarations. If it doesn't seem to be working, edit your question with the rendered javascript you see while inspecting the page source.
I have found the most reliable way to render any data, is to use the safe django template filter, so it doesn't try and encode any special fields.
return render(request,
'home.html',
{'labels': json.dumps(labels),'data': json.dumps(data)}
)
Then render using using the safe template filter. This
<script>
var labels = {{labels | safe}};
var data = {{data | safe}};
...
</script>
I am relatively new to Django framework and working on getting my first application running. I am encountering the below issue when i try to pass my queryset from my view to the template.
My view.py:
with connection.cursor() as cursor:
cursor.execute("SELECT TOP(5) * FROM xxx WHERE sbu = %s", [sbu])
def dictfetchall(cursor):
columns = [col[0] for col in cursor.description]
return [dict(zip(columns,row)) for row in cursor.fetchall()]
results = dictfetchall(cursor)
class DecimalEncoder(json.JSONEncoder):
def _iterencode(self, o, markers=None):
if isinstance(o, decimal.Decimal):
return (str(o) for o in [o])
return super(DecimalEncoder, self)._iterencode(o, markers)
json_result = json.dumps(data, cls=DecimalEncoder)
I end up with the below error:
Decimal('28.80') is not JSON serializable
Any suggestions? Am i missing a step somwhere? I have lot of decimal values in the queryset.
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