How can I send an data to chart.js in python django? - python

I'm making a project about pull a user github API like this one https://octoprofile.now.sh/user?id=nathannewyen
I don't know how to pass an data to another function in django
Here is my views.py:
def user(req, username):
username = str.lower(username)
# Get User Info
with urlopen(f'https://api.github.com/users/{username}') as response:
source = response.read()
data = json.loads(source)
# Get Limit Call API
with urlopen(f'https://api.github.com/rate_limit') as response:
source = response.read()
limit_data = json.loads(source)
# Get User Repo Info
with urlopen(f'https://api.github.com/users/{username}/repos') as response:
source = response.read()
sorted_by_stars = json.loads(source)
sorted_by_forks = json.loads(source)
sorted_by_size = json.loads(source)
# Sorted by stars
def sort_user_repo_by_stars(sorted_by_stars):
return sorted_by_stars['stargazers_count']
sorted_by_stars.sort(key=sort_user_repo_by_stars, reverse=True)
# Sorted by forks
def sort_user_repo_by_forks(sorted_by_forks):
return sorted_by_forks['forks']
sorted_by_forks.sort(key=sort_user_repo_by_forks, reverse=True)
# Sorted by size
def sort_user_repo_by_size(sorted_by_size):
return sorted_by_size['size']
sorted_by_size.sort(key=sort_user_repo_by_size, reverse=True)
created_at = data['created_at']
created_at = datetime.datetime.strptime(created_at, "%Y-%m-%dT%H:%M:%SZ")
created_at = created_at.strftime("%B %d, %Y")
context = {
'username': username,
'data': data,
'created_at': created_at,
'limit_data': limit_data,
'sorted_by_stars': sorted_by_stars[:8],
'sorted_by_forks': sorted_by_forks[:8],
'sorted_by_size': sorted_by_size[:8],
}
return render(req, 'user.html', context)
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
labels = ["Blue", "Yellow", "Green", "Purple", "Orange"]
default_items = [23, 2, 3, 12, 2]
data = {
"labels": labels,
"default": default_items,
}
return Response(data)
and here is my urls.py:
from django.urls import path
from . import views
from .views import ChartData
urlpatterns = [
path('', views.index),
path('search', views.searchUser),
path('<username>', views.user),
path('api/chart/data/', ChartData.as_view(), name='api-data'),
]
and here is my templates index.html:
<script>
var endpoint = '/api/chart/data/'
var defaultData = []
var labels = [];
$.ajax({
method: "GET",
url: endpoint,
success: function (data) {
labels = data.labels
defaultData = data.default
setChart()
},
error: function (error_data) {
console.log("error")
console.log(error_data)
}
})
function setChart() {
var ctx = document.getElementById("myChart");
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: labels,
datasets: [{
label: '# of Votes',
data: defaultData,
backgroundColor: [
'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)'
],
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
}
}]
}
}
});
}
</script>
<div class="card shadow">
<div class="card-body">
<h4 class="card-title">Top Languages</h4>
<div class="line"></div>
<p class="card-text">
<canvas id="myChart" width="150" height="150"></canvas>
</p>
</div>
</div>
I want to make an Top languages used chart like the link that I linked below.
How can I do that in python django?
I really appreciate it

To make your backend and your frontend communicate, you can use some sort of REST API between the two. This is a whole topic on its own so here is a solution to achieve what you want in a simple way.
Your django server is serving HTML files to your client. Those HTML files are called "templates" in the django world because they are rendered by your server. Sadly, once served to the client, you cannot execute python on those pages anymore... Hou have to find another way. Here is an idea:
As you can type JavaScript in an HTML file, you can make django render your data as something JavaScript can understand. JSON for example, or even directly JavaScript code. Keep in mind that this is often seen as a bad practice though, as it will make bugs harder to find.
In our case, we only need two things: x and y values.
Here is how to generate those in python, so that it can be turned into JavaScript:
labels = ['a', 'b', 'c', 'd', 'e']
values = [0, 0, 0, 0, 0]
return render('our_template.html', {
'x': json.dumps(labels),
'y': json.dumps(values),
})
This what we can write in our template to store the data as plain JavaScript variables:
let x = {{ x|safe }}; // this is django template markup language right here
let y = {{ y|safe }}; // it will get evaluated before returning the template to the client
The code above will get rendered as:
let x = ['a', 'b', 'c', 'd', 'e'];
let y = [0, 0, 0, 0, 0];
And here is how you will use them to make a simple bar chart:
window.addEventListener("DOMContentLoaded", event => {
let label = "My chart";
let ctx = document.getElementById('my-chart').getContext('2d');
let accessLogChart = new Chart(ctx, {
type: 'bar',
data: {
labels: x,
datasets: [{
label: label,
data: y,
}]
},
});
});

Related

javascript bar chart data no showing

This code gets the total_paid and total_due data:
#http.route('/dashboard', website=True, auth='public')
def TotalItems(self, **kw):
total_paid = 0.0
total_due = 0.0
payslips = request.env['student.payslip'].search([])
for payslip in payslips:
total_paid += payslip.paid_amount
total_due += payslip.due_amount
return http.request.render('daffodil_smartedu_dashboard.dashboard', {
'total_paid': total_paid,
'total_due': total_due
})
and I fetch this data in odoo website like this:
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.9.3/dist/Chart.min.js"></script>
<canvas id="myChart"></canvas>
<script>
var total_paid = parseFloat(total_paid);
var total_due = parseFloat(total_due);
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Total Paid', 'Total Due'],
datasets: [{
label: 'Amount',
data: [total_paid, total_due],
backgroundColor: [
'rgba(255, 99, 132, 0.2)',
'rgba(54, 162, 235, 0.2)'
],
borderColor: [
'rgba(255, 99, 132, 1)',
'rgba(54, 162, 235, 1)'
],
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: { beginAtZero: true }
}]
}
}
});
</script>
The bar chart is showing but the total_paid and total_due data is not showing. When I print this in console it is showing NaN. How can I fetch this data in a bar chart?

Replace ajax json for python json in Django

I'm trying change Ajax json url to python variable with a json in Django. As you can see the url in both cases are the same so I can't understand what is going on.
Thanks in advance.
What I'm looking for and does not work
<script>
$(document).ready(function() {
var table = $('#users').DataTable({
"ajax": "{{ es_docs }}",
my view:
#login_required(login_url="/login/")
def index(request):
context = {}
context['segment'] = 'index'
html_template = loader.get_template( 'index.html' )
resp = requests.get("https://gyrocode.github.io/files/jquery-datatables/arrays_id.json").json()
context['es_docs'] = resp
return HttpResponse(html_template.render(context, request))
Template.html:
<script>
$(document).ready(function() {
var table = $('#users').DataTable({
"ajax": "https://gyrocode.github.io/files/jquery-datatables/arrays_id.json",
'columnDefs': [
{
'targets': 0,
'checkboxes': {
'selectRow': true
}
}
],
'select': {
'style': 'multi'
},
'order': [[1, 'asc']]
});
This:
resp = requests.get(...)
Returns a response object. To get the json data do this:
response = requests.get(...)
if response.status_code != 200:
# handle errors:
else:
json_data = response.json()
context['es_docs'] = json_data

How to implement chart.js in Django?

I'm trying to visualize my data to a graph using chart.js!
However, I have no idea how that's done...
Could you program experts help me with this, please?
Here's the code I had so far
model.py
class MarksInputOne(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
date = models.DateTimeField(auto_now_add=True)
mark = models.CharField(max_length=200)
def __str__(self):
return self.mark
views.py
def courseOne(request):
marks = MarksInputOne.objects.filter(user=request.user)
total_assign = TodoList.objects.filter(user=request.user)
total = total_assign.count()
this = total_assign.filter(category__name="MAT292H1").count()
return render(request, 'courses/firstcourse.html', {'marks': marks, 'total_assign': total_assign, 'total': total,
'this': this})
def lineChart(request):
labels =[]
data = []
queryset = MarksInputOne.objects.values('mark').filter(category__name='MAT292H1').order_by('date')
for entry in queryset:
labels.append(entry['date'])
data.append(entry['mark'])
return JsonResponse(data={
'labels': labels,
'data': data,
})
and finally, chart.html, this is actually an example code from chart.js
<div class="col">
<div class="col-md">
<h5>Graph</h5>
<hr>
<div class="card card-body">
<canvas id="chart" width="800" height="400"></canvas>
<script>
var ctx = document.getElementById('chart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
data: {
labels: [{{data}}],
datasets: [{
label: 'Academic Performance',
data: [{{ labels }}],
fill: false,
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: [
'rgb(255,99,132)',
'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
}
}]
}
}
});
</script>
</div>
</div>
</div>
Please help me to implement the data on the chart!
I've been searching through internet for so long, couldn't find anything :((
Thank you for your help!!
All that chart.js cares about is a list of labels, and a list of values. So you'll have to somehow provide it with that. Your lineChart view function responds with a list of labels and a list of datapoints so it suits our needs exactly. What you'll need to do is have your web page send a request to your django server to request the data it should display. When a response is received, you can feed in your data to chart.js and build your chart. Here's a stripped-down code of how all of this fits together from the client's side and from the server's side:
Server Side
def lineChart(request):
return JsonResponse(data = {
'labels': ["Red Label", "Yellow Label"],
'data': [5, 6],
})
Client Side
<canvas id="chart"></canvas>
<script>
let ctx = document.getElementById('chart');
$.ajax({
url: '/lineChart/',
success: function(response){
new Chart(ctx, {
type: 'line',
data: {
labels: response.labels,
datasets: [{
data: response.data
}]
}
});
}
});
</script>
One thing I should point out are the different languages we are dealing with here and how they interact. Django renders an HTML page. During this rendering process, it has access to python variables called context variables. After it's done rendering, it sends that final HTML page to the client. On the client's side is chart.js which is a JavaScript library, it needs JavaScript variables to work with. So using Django's context variables wouldn't really work. ...unless... you use django to render its context variables into the html page as hard-coded javascript-vaild values. I'm guilty of doing this in the past but I would not recommend this approach. It smells awful!

AJAX post-ing of python dictionary leads to JSONDecodeError

I am passing a python dictionary to a template then $.post-ing it to a view in django,
and when I try to json.loads it in my post view, I get JSONDecodeError.
Anyone know how I can fix this?
//1. vars to templates
#login_required
def bracket(request):
'''
:param request:
:return:
'''
...
context = {'arr':json.dumps(tournament_games_json_serializable), 'nested':nested_tournament_games['rounds']}#{'latest_question_list': latest_question_list}
return render(request, 'madness/bracket.html', context)
//2. AJAX post of template var
$.post('{% url "update_bracket" %}',
{ bracketData: "{{arr}}" },
function(data, status, xhr) {
console.log(JSON.stringify(data));
var nested = JSON.stringify(data);
}).done(function() { })
.fail(function(jqxhr, settings, ex) { alert('failed, ' + ex); });
//3. update_bracket
#csrf_exempt
def update_bracket(request):
bracketData = request.POST['bracketData']
print(json.loads(bracketData))
...
where tournament_games_json_serializable is
tournament_games_json_serializable
{'round_1_game_1': {'players': (2, 3), 'winner': None, 'loser': None, 'done': False}, 'round_2_game_1': {'players': (1, 'winner of Round 1 Game 1'), 'winner': None, 'loser': None, 'done': False}}
request.POST['bracketData']
'{"round_1_game_1": {"players": [2, 3]...
json.loads(bracketData)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2
Use html.unescape():
import json
import html
bracketData = '{"round_1_game_1": {"players": [2, 3]}}'
print(json.loads(html.unescape(bracketData)))
Output:
{'round_1_game_1': {'players': [2, 3]}}
Did you try to use safe filter?
{ bracketData: "{{arr|safe}}" },

Plotly.js connecting to Django Rest Framework API - is this possible and if so how?

I am testing the use of plotly in our company's web application. I know plotly has it's own API but it is possible to connect to the Django Rest framework API since it is python based?
If it is possible - what does the syntax look like? Here is what I have so far:
div id="myDiv"></div>
<script>
var trace1 = {
x: [1, 2, 3, 4],
y: [10, 15, 13, 17],
type: 'scatter'
};
var trace2 = {
x: [1, 2, 3, 4],
y: [16, 5, 11, 9],
type: 'scatter'
};
var data = [trace1, trace2];
Plotly.newPlot('myDiv', data);
</script>
Instead of hard-coding the data in 'x' and 'y' - I want to point to the json in the Django rest Framework. Database is MySQL. Any help is greatly appreciated!!!
Thanks!
I'm not sure if this is what you're looking for, but in my case i needed it to connect to data from a model in django.
To do it i have this in my views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import MyModel
#api_view(['GET'])
def index(request):
entries = MyModel.objects
data = entries.values('x', 'y')
context = {
'x': [i['x'] for i in data],
'y': [i['y'] for i in data]
}
print(context)
return Response(context)
and in my plot.js file
import React from 'react';
import Plot from 'react-plotly.js';
class Plot extends React.Component {
state = {}
async reload () {
let url = '<django server address to view>'
const res = await fetch(url);
const info = await res.json();
console.log(info)
this.setState({
x: info.x,
y: info.y,
});
}
async componentDidMount() {
this.reload();
}
render() {
return (
<Plot
data={[
{
x: this.state.x,
y: this.state.y,
type: 'scatter',
mode: 'points-lines',
marker: {color: 'red'},
},
]}
layout={ {width: 600, height: 480, title: 'A Fancy Plot'} }
/>
);
}
}
export default Plot
from there you can use the Plot component in your react app.
However, i wonder if there's a more efficient way to do the query in django to handle huge amounts of data..

Categories

Resources