A bit of a general question - I am looking for ways to refresh a graph on a Django page based on user choices. The page has a graph, a few drop boxes where you can select parameters and a refresh button. Currently, I can capture the selections via ajax to my Django view and generate new data from database for the graph. I now need to feed that newly-generated data back into the graph and refresh it without a page refresh. Could anyone recommend the best methods of doing this?
Use JQuery to refresh graph without refreshing page.
I am using chart.js to create graph. first create a graph and on change event get updated data using Ajax URL call and assign values to chart data sets.
/** Graph Start Here */
window.chart = null;
$(document).on('change', '.graph-year-earning', function () {
var year = $(this).val();
$.get($('.graph-ajaxload-context').data('href'), { 'year': year, 'number': Math.floor(Math.random() * (1000000 - 10 + 1) + 10) }, function (response) {
window.chart.data.labels = response.labels;
window.chart.data.datasets[0].soldProductLabel = response.product_sold_label;
window.chart.data.datasets[0].totalCommissionLabel = response.monthly_commission_label;
window.chart.data.datasets[0].dataLabel = response.your_share_label;
if (response.total_commission == 0) {
window.chart.options.scales.yAxes[0].ticks.suggestedMin = 0;
window.chart.options.scales.yAxes[0].ticks.suggestedMax = 140000;
} else {
window.chart.options.scales.yAxes[0].ticks.suggestedMin = '';
window.chart.options.scales.yAxes[0].ticks.suggestedMax = '';
}
$.each(response.data, function (index, value) {
window.chart.data.datasets[0].soldProduct[index] = value[2];
window.chart.data.datasets[0].data[index] = Math.round(value[0]);
});
window.chart.update();
$(".txt-total-commission-by-year").html(response.total_commission)
$('.graph-ajaxload-context .inline-loader').hide();
});
});
if ($('.graph-ajaxload-context').length > 0) {
showLoader()
$('.graph-year-earning').trigger('change');
var ctx = $('#userEarningGraph');
window.chart = new Chart(ctx, {
type: 'bar',
data: {
labels: [],
datasets: [{
soldProductLabel: '',
soldProduct: [],
dataLabel: '',
data: [],
backgroundColor: '#ADAEB1',
hoverBackgroundColor: '#48C6B9'
}]
},
options: {
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
maxTicksLimit: 8,
userCallback: function (value, index, values) {
value = value.toString();
value = value.split(/(?=(?:...)*$)/);
value = value.join(',');
var currency_code = ' ₩'
if ($('.graph-ajaxload-context').data('currency-code') && $('.graph-ajaxload-context').data('currency-code') != 'None') {
currency_code = $('.graph-ajaxload-context').data('currency-code')
}
return value + ' ' + currency_code;
}
},
}]
},
tooltips: {
mode: 'label',
callbacks: {
label: function (tooltipItem, data) {
var soldProduct = data.datasets[tooltipItem.datasetIndex].soldProduct[tooltipItem.index];
var soldProductLabel = data.datasets[tooltipItem.datasetIndex].soldProductLabel;
var dataPro = data.datasets[tooltipItem.datasetIndex].data[tooltipItem.index];
var dataLabel = data.datasets[tooltipItem.datasetIndex].dataLabel;
return [soldProductLabel + ':' + soldProduct, dataLabel + ':' + dataPro + ' ₩',];
}
}
}
}
});
}
$(document).on('click', '.showgraph', function (e) {
$('.graph-year-earning').trigger('change');
});
/** Graph End Here */
Related
I am working with Clarifai's API to write the returned responses to a CSV. For each image I submit, I want to take the top 5 images and append their metadata to a row in a data frame with the file_id as the first column. So each image would have 5 rows with the metadata attached to it in each successive columns. I seem to be generating some dictionary entries where the order of the values in the list being appended isn't preserved and I am trying to figure out why. This is a sample response I am iterating over.
[score: 0.8935652375221252
input {
id: "1002648140"
data {
image {
url: "https://images.lowes.com/product/converted/192665/192665007798.jpg"
hosted {
prefix: "https://s3.amazonaws.com/clarifai-api/img3/prod"
suffix: "3617f25f9ee5463497e7abf350091b93/c1ee1a24260772d532f0d371ac08fb06"
sizes: "orig"
sizes: "tiny"
sizes: "small"
sizes: "large"
}
}
metadata {
fields {
key: "cat_entry_id"
value {
string_value: "1002648140"
}
}
fields {
key: "catalog_name"
value {
string_value: "Roses"
}
}
fields {
key: "catalog_path"
value {
string_value: "Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Roses"
}
}
fields {
key: "link_url"
value {
string_value: "https://www.lowes.com/pd/Spring-Hill-Nurseries-in-Bare-Root-Red-Flowering-Blaze-Climbing-Rose/1002648140"
}
}
fields {
key: "product_name"
value {
string_value: "Spring Hill Nurseries in Bare Root Red Flowering Blaze Climbing Rose"
}
}
}
clusters {
id: "985_203"
}
}
created_at {
seconds: 1599796898
nanos: 391916000
}
modified_at {
seconds: 1599798078
nanos: 291417000
}
status {
code: INPUT_DOWNLOAD_SUCCESS
description: "Download complete"
}
}
annotation {
id: "c588c2f17f01465f94bde2d2c2e5687f"
input_id: "1002648140"
data {
}
status {
code: ANNOTATION_SUCCESS
description: "Annotation success"
}
created_at {
seconds: 1599798076
nanos: 759651000
}
modified_at {
seconds: 1599798076
nanos: 759651000
}
model_version_id: "bb186755eda04f9cbb6fe32e816be104"
}
, score: 0.8807249665260315
input {
id: "1000383061"
data {
image {
url: "https://images.lowes.com/product/converted/743425/743425079649.jpg"
hosted {
prefix: "https://s3.amazonaws.com/clarifai-api/img3/prod"
suffix: "3617f25f9ee5463497e7abf350091b93/756b268566daea823f07248208c05e21"
sizes: "orig"
sizes: "tiny"
sizes: "small"
sizes: "large"
}
}
metadata {
fields {
key: "cat_entry_id"
value {
string_value: "1000383061"
}
}
fields {
key: "catalog_name"
value {
string_value: "Annuals"
}
}
fields {
key: "catalog_path"
value {
string_value: "Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Annuals"
}
}
fields {
key: "link_url"
value {
string_value: "https://www.lowes.com/pd/3-Quart-Purple-Purple-Garden-Mum-in-Pot/1000383061"
}
}
fields {
key: "product_name"
value {
string_value: " 3-Quart Purple Purple Garden Mum in Pot"
}
}
}
clusters {
id: "54_203"
}
}
created_at {
seconds: 1599795418
nanos: 883441000
}
modified_at {
seconds: 1599795429
nanos: 301624000
}
status {
code: INPUT_DOWNLOAD_SUCCESS
description: "Download complete"
}
}
annotation {
id: "91434754e4bd425ba3c528be9cd901e0"
input_id: "1000383061"
data {
}
status {
code: ANNOTATION_SUCCESS
description: "Annotation success"
}
created_at {
seconds: 1599795427
nanos: 683212000
}
modified_at {
seconds: 1599795427
nanos: 683212000
}
model_version_id: "bb186755eda04f9cbb6fe32e816be104"
}
I am using a dictionary and adding the value of metadata as a list and not getting the same order of the lists being appended. Please see the following sample dictionary for reference.
{'test_output/fe_IMG_0574.jpg_0': ['Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Roses',
'https://www.lowes.com/pd/Spring-Hill-Nurseries-in-Bare-Root-Red-Flowering-Blaze-Climbing-Rose/1002648140',
'Roses',
'Spring Hill Nurseries in Bare Root Red Flowering Blaze Climbing Rose',
'1002648140'],
'test_output/fe_IMG_0574.jpg_1': ['https://www.lowes.com/pd/3-Quart-Purple-Purple-Garden-Mum-in-Pot/1000383061',
'1000383061',
' 3-Quart Purple Purple Garden Mum in Pot',
'Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Annuals',
'Annuals'],
'test_output/fe_IMG_0574.jpg_2': ['https://www.lowes.com/pd/4-Count-Dahlia-Bulbs-L3480/1000151071',
'1000151071',
' 4 Count Dahlia Bulbs (L3480)',
'Outdoors$Plants & Planters$Plants, Bulbs & Seeds$Plant Bulbs',
'Plant Bulbs']}
which then creates a data frame that has different values for columns in what seems like sporadic rows. This is the code I am using to generate this.
final_dict = {}
for i in range(5):
response_object = response.hits[i].input.data.metadata.items()
final_list = []
url = response_object[0][1]
product_name = response_object[1][1]
catalog_entry_id = response_object[2][1]
catalog_path = response_object[3][1]
catalog_name = response_object[4][1]
final_list.append(url)
final_list.append(catalog_entry_id)
final_list.append(product_name)
final_list.append(catalog_path)
final_list.append(catalog_name)
final_dict[file_id+'_'+str(i)] = final_list
print(final_dict)
final_df = pd.DataFrame.from_dict(final_dict, orient='index')
Please see the following rows as an example of what I mean
This is for posterity. The new Clarifai GRPC client has different data structuring. So as a result, I had to parse them by first listing fields. This is what my final loop looked like. It had the ListFields added line
for i in range(5):
response_object = response.ListFields()[1]
test_meta = response_object[1][i].input.data.metadata
final_list = []
url = test_meta['link_url']
product_name = test_meta['product_name']
catalog_entry_id = test_meta['cat_entry_id']
catalog_path = test_meta['catalog_path']
catalog_name = test_meta['catalog_name']
final_list.append(i+1)
final_list.append(url)
final_list.append(catalog_entry_id)
final_list.append(product_name)
final_list.append(catalog_path)
final_list.append(catalog_name)
final_dict[file_id+'_'+str(i)] = final_list
I use DataTable in my Django project and currently doing internationalisation of my apps
I would like DataTable change with browser language as for my templates.
I have found the way to change language with DataTable option
var table = $('#table_id').DataTable({
lengthMenu: [5,10],
"language": {
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/French.json"
}
});
is their a simple way doing it?
or should I test for browser language and have a switch to initialize var table?
something like that (pseudocode):
if browser.lang == 'english'{
var table = $('#table_id').DataTable({
lengthMenu: [5,10],
});
}
else {
var table = $('#table_id').DataTable({
lengthMenu: [5,10],
"language": {
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/French.json"
}
});
}```
Try to make a comparision between:
var lang = navigator.languages && navigator.languages[0] ||
navigator.language || navigator.userLanguage;
Var language is different on current browsers
thanks to Synapsido that show me the way...
below the code I use
<script>
$(document).ready( function () {
if(window.navigator.language == 'fr-FR'){
var table = $('#table_id').DataTable({
lengthMenu: [5,10],
"language": {
"url": "//cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/French.json"
}
});
} else {
var table = $('#table_id').DataTable({
lengthMenu: [5,10],
});
}
I'm having trouble getting data from the backend (Python API) to show in react-table manually. I've read the documentation and I'm trying to use the example here: https://react-table.js.org/#/story/server-side-data
I'm only seeing data in one column and only for 6 records which is really weird. It's probably the way I'm mixing in async/await syntax with the example code which uses a promise. I was able to create a simple react-table fetching data with the same async/await syntax, but when I added the server-side data code from the example (the requestData function) it wouldn't work.
I've spent days on this and looking all over Stackoverflow and the internet. I'm a newbie so please go easy on me. Here's what I have:
import React from 'react'
import { render } from 'react-dom'
import ReactTable from 'react-table'
import api from 'src/api'
import { orderBy } from 'lodash'
// importing react-table css would not work so I added it using cdn link
const requestData = async (pageSize, page, sorted, filtered) => {
// api is a wrapper for axios.create()
const rawData = await api.admin.exercise.feed()
return new Promise((resolve, reject) => {
let filteredData = rawData;
if (filtered.length) {
filteredData = filtered.reduce((filteredSoFar, nextFilter) => {
return filteredSoFar.filter(row => {
return (row[nextFilter.id] + "").includes(nextFilter.value);
});
}, filteredData);
}
const sortedData = orderBy(
filteredData,
sorted.map(sort => {
return row => {
if (row[sort.id] === null || row[sort.id] === undefined) {
return -Infinity;
}
return typeof row[sort.id] === "string"
? row[sort.id].toLowerCase()
: row[sort.id];
};
}),
sorted.map(d => (d.desc ? "desc" : "asc"))
);
const res = {
rows: sortedData.slice(pageSize * page, pageSize * page + pageSize),
pages: Math.ceil(filteredData.length / pageSize)
};
resolve(res);
});
};
export class ExerciseList extends React.Component {
constructor() {
super();
this.state = {
data: [],
pages: null,
loading: true
};
this.fetchData = this.fetchData.bind(this);
}
setLoading(loading) {
this.setState({ loading })
}
fetchData(state, instance) {
this.setLoading(true);
requestData(
state.pageSize,
state.page,
state.sorted,
state.filtered
).then(res => {
this.setState({
data: res.rows,
pages: res.pages,
loading: false
});
});
}
render() {
const { data, pages, loading } = this.state;
return (
<div>
<ReactTable
columns={[
{
Header: "Name",
accessor: "name"
},
{
Header: "Movement",
accessor: "movement"
},
{
Header: "Equipment",
accessor: "equipments"
},
{
Header: "Channel",
accessor: "channel"
},
{
Header: "Level",
accessor: "skill_level"
},
{
Header: "Duration",
accessor: "duration",
filterable: false
},
{
Header: "Injuries",
accessor: "injuries"
},
{
Header: "Is Substitute",
accessor: "has_video",
Cell: ({ value }) => (value? 'Yes': 'No'),
filterable: false
}
]}
data={data}
pages={pages}
loading={loading}
onFetchData={this.fetchData}
manual
filterable
defaultPageSize={10}
className="-striped -highlight"
/>
</div>
);
}
}
render(<ExerciseList />, document.getElementById('datatable'));
Please refer the link for server-side sorting, pagination and manual filtering within the grid
// Component related to methods for sorting, pagination server side and filtering manual filtering with in the grid
import React from 'react'
import 'react-table/react-table.css'
import ReactTable from 'react-table'
import autoBind from 'react-autobind'
import {filterCaseInsensitive} from '../../helper/commonMethods'
class ServerSideAtomGrid extends React.Component {
super(props)
const userDetails = getUserDetails()
this.state = {
page: 0,
pageSizeOptions: [500, 1000, 2000, 4000],
pageSize: 500,
totalRecords: 0,
nextCursor: '*',
cursorList: [{
page: 0,
cursor: '*'
}],
sortFields: {
field: 'created_dtm',
sort: 'desc'
},
columnData,
}
autoBind(this)
}
handlePageChange (page) {
const pageNumber = (page)
const cursorList = this.state.cursorList
let cusrsorMark = ''
_.each(cursorList, (list) => {
if (list.page === pageNumber) {
cusrsorMark = list.cursor
}
})
this.setState({
nextCursor: cusrsorMark,
page: pageNumber
}, () => this.searchData(cusrsorMark, pageNumber))
}
handleSizePerPageChange (pageSize) {
this.resetData(pageSize)
this.searchData('*', 0)
}
handleSorting = (state, instance) => {
const sorted = state
let field = 'created_dtm'
let sort = 'desc'
sorted && sorted.length > 0 && sorted.map(fld => {
field = fld.id
sort = fld.desc ? 'desc' : 'asc'
})
this.setState({
sortFields: {
field,
sort
}
}, () => this.searchData('*', 0))
}
////
searchData('*', 0) {
//Axios call you cna have
}
filterCaseInsensitive (filter, row) {
const id = filter.pivotId || filter.id
return row[id] ? row[id].toString().toLowerCase().includes(filter.value.toLowerCase()) : true
}
render () {
const {
classes, gridData, gridColumns, defaultFilter, totalRecords,
gridPageSizeOptions, gridPage, gridPages, gridPageSize, gridLoading
} = this.props
return (
<div>
<ReactTable
columns={gridColumns}
data={gridData}
onSortedChange={(state, instance) => {
this.handleSorting(state, instance)
}}
filterable={defaultFilter}
defaultFilterMethod={filterCaseInsensitive}
noDataText="Ops No result found!"
defaultPageSize={this.state.pageSize}
className="-highlight"
style={{height: `${totalRecords < 25 ? '' : `800px`}`, width: '100%', textAlign: 'center'}}
pageText={`Total Count : ${totalRecords.toLocaleString()} Page: `}
loading={gridLoading}
page={this.state.page}
pages={this.state.pages}
showPaginationTop
pageSize={this.state.pageSize}
pageSizeOptions={gthis.state.pageSizeOptions}
minRows={25}
manual
onPageChange={page => {
this.setState({page})
this.handlePageChange(page)
}}
onPageSizeChange={(pageSize, page) => {
this.setState({
page,
pageSize
})
this.props.handleSizePerPageChange(pageSize)
}}
showPageJump={false}
/>
</div>
)
}
}
export default (ServerSideAtomGrid)
My Fiddle: https://jsfiddle.net/gowthamguruju/o9ybxqaj/8/
Angularjs code
var app = angular.module('myApp', []);
app.factory('httpSend', ['$http', '$q', function($http, $q) {
var app = {};
app.sendToServer = function(data) {
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-type': 'application/x-www-form.urlencoded;'
}
}).then(function(response) {
debugger
var result = data;
});
}
app.getfromServer = function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
return app;
}]);
app.controller('myCtrl', ['$scope', '$http', 'httpSend', '$filter', function($scope, $http, httpSend, $filter) {
$scope.names = ["ankit patidar", "adhishi ahari", "kritin joshi", "kautilya bharadwaj", "punita ojha", "manvi agarwal", "apeksha purohit", "shipra jain", "mansi nangawat", "praveen soni"];
$scope.data = [];
$scope.names.forEach(function(name) {
$scope.data.push({
name: name,
checkin: "",
checkout: ""
})
});
$scope.login = [];
$scope.check = function(name, doing) {
debugger
name[doing] = new Date();
name[doing] = $filter('date')(name[doing], 'dd-MM-yyyy hh:mm:ss');
$scope.login.push(angular.copy(name));
if (doing == "checkout") {
var q = JSON.stringify($scope.login);
httpSend.sendToServer(q);
}
}
$scope.getData = function() {
httpSend.getfromServer();
}
}]);
`
Python Code
def get(self):
logging.info('get is triggered')
obj = CheckIn.query().fetch()
emp_obj = []
for x in obj:
logging.info('I am inside for loop ')
emp_obj.append({
'name': x.name,
'Check_in': x.inDate,
'check_out': x.outDate
})
logging.info('I am inside emp_obj')
self.response.write(json.dumps(emp_obj))
i need to fetch all the data stored on ndb datastore on front end view thats why i m using http get method but error is showed method not allowed. can u please help e despite using query fetch and showing its response on python ad triggering get method, why error is coming, is there a mistake in control flow or something is missing in my get method, as for now i m able to post nd store data
Change your factory to the following. Don't use the same variable app that you are using for initialising your module for your controller logic.
app.factory('httpSend',['$http', '$q',function($http, $q){
return {
'sendToServer': function(data) {
var def = $q.defer();
$http({
method: "POST",
url: '/report',
data: data,
headers: {
'Content-Type': 'application/json'
}
}).then(function(response) {
debugger
var result = response.data;
def.resolve(result );
});
return def.promise;
},
'getfromServer': function() {
var def = $q.defer();
$http.get('/report').then(function(data) {
console.log(data);
def.resolve(data);
}),
function(error) {
def.reject("Failed to get albums");
};
return def.promise;
}
}
}]);
I have parsed JSON from those models in the view to a JsonResponse and now I am trying to my multi-line plot working using d3.js.
The example code I am trying to use is here.
I am not sure how to go about changing the tsv call or if I should change my JSON format.
d3.tsv("data.tsv", function(error, data) {
if (error) throw error;
color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
data.forEach(function(d) {
d.date = parseDate(d.date);
});
var cities = color.domain().map(function(name) {
return {
name: name,
values: data.map(function(d) {
return {date: d.date, temperature: +d[name]};
})
};
});
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
]);
And here is how my JSON is formatted where the Site name is top level, and the `Metric is one level deep.
{ "Site1":
[{"da": 1.0, "date": 2015-09-01},
{"da": 2.0, "date": 2015-09-04}],
"Site2":
[{"da": 1.0, "date": 2015-09-01},
{"da": 2.0, "date": 2015-09-04}
{"da": 5.0, "date": 2015-09-04}]
}
How can I setup d3.js to work with these nested JSON objects versus the top level JSON in the example?
Here is the full working code fiddle; I have added comments in the code to help you understand the code.
Fiddle
Full code snippet:
var margin = {
top: 20,
right: 80,
bottom: 30,
left: 50
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
var color = d3.scale.category10();
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var line = d3.svg.line()
.interpolate("basis")
.x(function (d) {
return x(d.date);
})
.y(function (d) {
return y(d.da);
});
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//your dataset
var myData = {
"Site1": [{
"da": 1.0,
"date": "2015-09-01"
}, {
"da": 2.0,
"date": "2015-09-04"
}],
"Site2": [{
"da": 1.0,
"date": "2015-09-01"
}, {
"da": 2.0,
"date": "2015-09-04"
}, {
"da": 5.0,
"date": "2015-09-04"
}]
};
//make fulldataset to get the extent of x axis and yaxis
var fullDataSet = []
for (var key in myData) {
fullDataSet = fullDataSet.concat.apply(fullDataSet, myData[key]);
}
fullDataSet.forEach(function (d) {
d.date = parseDate(d.date);
d.da = +d.da;
});
//get the xaxis extent i.e. min max
x.domain(d3.extent(fullDataSet, function (d) {
return d.date;
}));
//get the yaxis extent i.e. min max
y.domain(d3.extent(fullDataSet, function (d) {
return d.da;
}));
//make the x axis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
//make the y axis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("DA ");
//iterate through your nested data and make the line graph
for (var key in myData) {
makeLine(myData[key], key);
}
//This function will make the line chart
function makeLine(data, title) {
svg.append("path")
.datum(data)
.attr("class", "line")
.style("stroke", function (d) {
return color(title);
}).attr("d", line);
}