Display bar chart values from database with symfony 4 - javascript

I'm trying to display values from my database using symfony 4, twig and javascript in bar chart graphic this is how my bar chart should look like
but this is what 've got
this is my code
<script>
{% for stock in stocks %}
var barChartData = {
labels : ["{{ stock.idproduit.nom }}"],
datasets : [
{
fillColor : "#FC8213",
data : [{{ stock.quantite }}]
}
]
};
new Chart(document.getElementById("bar").getContext("2d")).Bar(barChartData);
{% endfor %}

Related

Django: Group and then Calculate the Sum of the column values through query

I have a model:
lifecycle_status_choice = (
('Lead', 'Lead'),
('Opportunity', 'Opportunity'),
('Customer', 'Customer'),
)
bill_status_choice = (
('Paid','Paid'),
('Pending','Pending'),
('Partially Paid','Partially Paid'),
)
class Bill(models.Model):
company_name = models.ForeignKey(Contact, on_delete=models.CASCADE)
grand_tot = models.DecimalField(max_digits=9, decimal_places=2)
status = models.CharField(max_length=100, choices=bill_status_choice)
lifecycle_status = models.CharField(max_length=100, choices=lifecycle_status_choice)
...
which has a fk to:
class Contact(models.Model):
associated_company = models.CharField(max_length=100)
...
Views.py
...
from bills.models import Bill
from django.db.models import Sum
def home(request):
data = Bill.objects.all().order_by('date')
context = {
'data ':data ,
}
return render(request, 'home.html',context)
Front end chartsjs:
const ctx = document.getElementById('myChart').getContext('2d');
const myChart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: [
{% for data in data %} '{{data.company_name}}', {% endfor %}
],
datasets: [{
label: '# of Votes',
data: [{% for data in data %} {{ data.grand_tot }}, {% endfor %}],
The problem:
I am using charts.js in my front end template and I am trying to display a chart in which as a user creates new company names the chart should display the total amount grouped by company names how would I achieve that?
eg:
I create two invoices for "xyz" company with amounts: $100 & $200 || & create one invoice for "abc" company with amount $100
I want the chart to group the "xyz" invoice amounts and display $300 (ie:100+200) || & "abc" = $100
FYI I'm aware I'm using something completely wrong in the view function but its just something that I tried.
Thanks
You can .annotate(…) [Django-doc] with:
from django.db.models import Sum
Contact.objects.annotate(bills_total=Sum('bill__grand_tot'))
The Contact objects that arise from this QuerySet will have an extra attribute .bills_total.
You can filter this with as satus paid with:
from django.db.models import Q, Sum
contacts = Contact.objects.annotate(bills_total=Sum('bill__grand_tot', filter=Q(bill__status='Paid')))
You can thus for example render this with:
{% for contact in contacts %}
{{ contact.associated_company }}: {{ contact.bills_total }}
{% endfor %}
or convert it to a list of Python dictionaries for example and then return it as a JSON blob.

Visual Studio Code: Jinja Curly Braces inline for Javascript variable

I am trying to get Jinja braces to stay in line for a javascript variable used in an apexchart.js call for a flask HTML page.
labels = JSON.parse({{ labels | tojson}})
data = JSON.parse({{ data | tojson}})
The problem I am having is that when I save the html the braces get formatted apart.
labels = JSON.parse({
{
labels | tojson
}
})
data = JSON.parse({
{
data | tojson
}
})
Is there away to stop Visual Studio Code from splitting the Jinja code apart?
Current Code Below:
<!-- language: lang-html -->
<!-- templates/index.html -->
{% extends 'base.html' %} {% block content %}
<title>Dashboard | {{title}}</title>
<div class="flex h-screen justify-center">
<div id="chart" class="h-1/4 w-1/2 content-center"></div>
</div>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<script>
labels = JSON.parse({
{
labels | tojson
}
})
data = JSON.parse({
{
data | tojson
}
})
var options = {
colors: ['#01ca95'],
chart: {
type: 'bar'
},
dataLabels: {
enabled: false
},
series: [{
name: 'sales',
data: data
}],
xaxis: {
categories: labels
},
yaxis: {
labels: {
formatter: function(data) {
//Setup new Formatting class variable
var Formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
return Formatter.format(data);
}
}
},
}
var chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
</script>
{% endblock content %}

nunjucks fetch data from input

I am trying to retrieve below field values in nunjucks following below template
Json data -
{
"user": {
"custom": [
{
"payload": "{ f_name=user, l_name=name, source=facebook, contact=email }"
}
]
}
}
Nunjucks Template -
{% set u = user %}
{% set data = u['custom'][0]['payload'] %}
Hello {{ data }}
This returns the below output
Hello { f_name=user, l_name=name, source=facebook, contact=email }
However, I would like to get the individual elements from the {{data}}
How can I fetch the f_name, l_name, source, contact fields from the above json data.
Please note the payload is a string and not a json object
You don't show us how user is pulling your JSON data into nunjucks, so I'll just spill out my take on this. Take advantage of the JavaScript split method, and the template engine loops and filters to give you the results you need.
I'm assuming there is more to your JSON data. If so, here is a short guide to help pull your 4 string items out of payload.
The JSON Data:
//sample JSON Data
const sampleData = [{
"user": {
"custom": [{
"payload": "{ f_name=user, l_name=name, source=facebook, contact=email }"
}]
}
}];
module.exports = sampleData;
The View:
{% for string in mSampleData %} //mSampleData is similar to your "user" template object.
{% for mval in string['user']['custom'] %}
{% set mstring = mval['payload'].replace('{', '').replace('}', '') %}
{% set marray = mstring.split(",") %}
{% set fname = marray[0].replace('f_name=', '') %}
{% set lname = marray[1].replace('l_name=','') %}
{% set source = marray[2].replace('source=','') %}
{% set contact = marray[3].replace('contact=','') %}
<p>{{fname}}</p>
<p>{{lname}}</p>
<p>{{source}}</p>
<p>{{contact}}</p>
{% endfor %}
{% endfor %}
The results:
user
name
facebook
email

how can I add a django array element into a js array using an if condition

I have a Django project with data being submitted by form , I am trying to use chart.js to display the data. I need to check whether an array exists() if so then add an item to 'labels' array in 'mycharts.js' . Heres what I have so far
django views.py
ing1 = request.POST.getlist('ingredients1')
ing2 = request.POST.getlist('ingredients2')
ing3 = request.POST.getlist('ingredients3')
( I've passed the above into my context )
mycharts.js
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {chart.js
labels: ['{{ing1.0}}', '{{ing2.0}}', {% if ing3|length > 1 %} '{{ing3.0}}', {% endif %}],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
(etc...)
if I take out the if statement inside of 'labels' array , then it shows the 'ing1' and 'ing2' headings , but I can't get it to work with this if statement , whats the correct way of doing it.
I put 'ing1, 'ing2' and 'ing3' into a list called 'title' inside my views , then put that list into the context , then did the following inside the chart.js script :
{% for item in title %} '{{ item }}', {% endfor %}
now it adds the correct data to the labels array.

Generate multiple line charts in Django with ChartJS

i'm working in Django, to draw some graph in function of my modules. ie: if i have 2 modules, i want 2 charts , if 8 modules, 8 charts.
Modules are integreted in a plugin. so i can list all modules found in a plugin. i did this in Django:
def plugin_graph(request, hub_uid, plugin_uid):
request.session['is_admin'] = True
hub = Hub.objects.get(mac=hub_uid)
fields = []
if request.method == 'GET':
if 'field' in request.GET:
fields.append(request.GET['field'])
plugin = Plugin.objects.get(uid=plugin_uid, hub=Hub.objects.get(mac=hub_uid))
#on recupere lensemble desmodules de ce plug
modules = plugin.get_modules_list()
#pour chak module, tracer son graph
for m in modules:
modules_list = {'uid':m.uid,
'name':m.name,
'version':m.version,
'type':m.type,
'time':m.last_time(),
'rssi':m.rssi(),
'status_icon':m.status_icon()}
module = Module.objects.get(uid=m.uid, plugin=Plugin.objects.get(uid=plugin_uid, hub=Hub.objects.get(mac=hub_uid)))
historic = sorted(ModuleDocument.objects.filter(module=module), key=getKey)
values = get_graph_values(historic=historic, dates=None, fields=fields)
print values
field = None if len(fields) < 1 else fields[0]
return render(request, "admin/graph2.html",
{
'values': values,
'hub': hub_uid,
'plugin': plugin_uid,
'uid': m.uid,
'module': module,
'fields': module.get_number_fields(),
'field': field,
'level': 'module',
}
)
After recovering all my modules i draw the charts like that in javascript:
<script>
var ctx = document.querySelector("#chart");
var data = JSON.parse('{{ values }}'.replace(/"/g, '"'));
var labels = [];
var values = [];
var beginAtZero = true;
for (obj in data) {
labels.push(data[obj].x);
values.push(data[obj].y);
if (data[obj].y < 0) {
beginAtZero = false;
}
}
var lineChart = new Chart(ctx, {
type: 'line',
data: {
labels: labels,
datasets: [{
label: "{{field}}",
data: values,
borderColor: '#97168F'
}]
},
options: {
scales: {
xAxes: [{
time: {
unit: 'day'
}
}],
yAxes: [{
ticks: {
beginAtZero:beginAtZero
}
}]
}
}
});
</script>
My problem is just one chart is printed. i would like to put it in a for loop to recuperate all data & labels of each module to draw normally all charts i want.
Thank u for your help
You need to utilise the forloop.counter method in the django template to dynamically name a number of items, otherwise the charts will just get overwritten each time and you are just left with the last chart. Its worth noting that I include this code in the block content not a specific js block.
In the example below, the items that are dynamically named are;
The container div
<div id = 'emg-{{forloop.counter}}'>
The canvas
<canvas id="myChart-{{forloop.counter}}">
The chart JS function name
var func_name = "container-{{forloop.counter}}";
func_name = new Chart(
document.getElementById('myChart-{{forloop.counter}}'),{
type: 'scatter',
I've included the full code below. I appreciate my example is different from your posted code, but it demonstrates the concept of dynamically creating certain elements.
{% for time, name_list, value_list, latitude_list, longitude_list, polyline_list in data %}
{% with forloop.counter as track_object_counter %}
<div id = 'emg-{{forloop.counter}}'>
{% for item in emg_data %}
{% if item.loop_id == track_object_counter %}
<div id = "emg-plot" style="height:15rem; padding-top: 1rem;">
<canvas id="myChart-{{forloop.counter}}">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
var y_data = {{item.data|strip_apostrophe}}
var x_data = '{{item.name}}'
var func_name = "container-{{forloop.counter}}";
func_name = new Chart(
document.getElementById('myChart-{{forloop.counter}}'),{
type: 'scatter',
data: {
datasets: [{
showLine: true,
label: x_data,
data: y_data,
backgroundColor: 'rgba(141,49,123,0.7)',
borderWidth: 2,
borderColor: 'rgba(141,49,123,0.7)'
}],
},
});
</script>
</canvas>
</div>
{% endif %}
{% endfor %}
</div>
{% endwith %}
{% endfor %}

Categories

Resources