Serving generated charts via AJAX - ajax

The workflow for my Django project should go like this:
User specifies parameters for chart generation
Chart is generated using matplot
Chart is then served to the user using AJAX
The possible number of charts to be generated is very large, because of differences in various parameters, so generating the charts beforehand and serving them statically is not an option.
The matplot commands show() and savfig() don't seem to be suited to the task either.
How best can I achieve this?

Roughly like this:
import django.http
import matplotlib.pyplot
# This is your view function, hook it up to your URLconf.
def chart(request, *args):
# ...extract chart parameters from request.GET and/or args...
fig = matplotlib.pyplot.figure(...)
# ...draw your chart, invoking methods on fig...
response = django.http.HttpResponse(content_type='image/png')
fig.savefig(response, format='png')
return response
Now I’m not sure how you would use AJAX to display this to the user. I think it would be easier to just insert img elements with appropriate src attributes. With jQuery, maybe like this:
var src = '/chart/?' + $.param({
// This all ends up in request.GET
type: 'something',
foo: 'bar',
myParam: 123
});
$('#displayArea').empty().append($('<img>').attr('src', src));
But if you do want AJAX, you can of course just use $.ajax.
If a chart is completely defined by the parameters passed in, and a user will likely want to see the same chart several times, consider setting liberal client caching headers to avoid re-requesting the same image from your server. This is just an optimization though.

Related

django_filter Django Rest Framework (DRF) handling query_params get vs getlist

Is it correct that filtering by a list of values remains overly complicated in django_filter and, by extention, the Django Rest Framework (DRF) or am I missing something simple?
Specifically, Must we specify a-priori the parameters that should be handled with 'getlist' rather than with 'get' when we process a multi-value parameter submitted via URL like below:
http://example.com?country=US&country=CN
Now, when we process this request,
request.query_params.get('country') as well as request.query_params['country'] will erroneously return 'CN' while request.query_params.getlist('country') will return ['US','CN'], which is what we wish in this example.
So my current logic dictates that I have to specify in advance which parameters may have multiple values specified, as I don't know of an internal method that handles this transparently:
So to handle this I currently do something like this (skipping all the actual request processing, filtering, etc. for the sake of simplicity):
class CountryFilter(filters.FilterSet):
""" placeholder: this is a separate question as to why I can't get any of these to work as desired. """
#country = filters.CharFilter(method='filter_country')
#country = filters.CharFilter(name='country', lookup_expr='in')
#country = filters.MultipleChoiceFilter()
class CountryViewSet(viewsets.ModelViewSet):
"""Viewset to work with countries by ISO code"""
def list(self, request, *args, **kwargs):
"""do something based on a request for one or more countries
such as http://example.com?country=CA&country=CN&country=BR
"""
query_params = request.query_params
filter0 = CountryFilter(query_params, queryset=Country.objects.all())
# if filter0 worked, we'd be done and wouldn't need below
# but it doesn't
query_dict = {}
params_to_list = ['country', 'another_param']
for k in query_params.keys():
if k in params_to_list:
query_dict[k] = query_params.getlist(k)
else:
query_dict[k] = query_params.get(k)
# use the newly counstructed query_dict rather than query_params
filter1 = CountryFilter(query_dict, queryset=Country.objects.all())
import pdb; pdb.set_trace()
return HttpResponse('ok')
In theory, filter1 should give me the desired results while filter0 will not.
Code based on this works in my production environment but has some other effects like turning the valid list back into a string. I don't want to drift into that question here, just wondering if this is what people do or not?
Specifically, Must we specify a-priori the parameters that should be handled with 'getlist' rather than with 'get' when we process a multi-value parameter submitted via URL like below:
This is not necessary. Filter instances construct a form field that in turn performs the query param validation. These fields are standard Django form fields, and its widget will determine whether or not to use .getlist() or .get() when extracting values from the query dict. You do not need to preprocess the query dict.
In your example, filter0 and filter1 should actually behave identically, since QueryDict('a=1&a=2') is functionally equivalent to dict(a=['1', '2']) for SelectMultiple widgets. Its .value_from_datadict() will call .getlist() on the former and .get() on the latter - both will return a list of values.
As to solving your issue of filtering by multiple values, you have two options.
Use a MultipleChoiceFilter (docs)
Use a CSV-based filter (docs)
Multiple choice filters render a select multiple widget and expects a querystring like ?a=1&a=b. You attempted this above, however you omitted choices. Without choices, the html select will be rendered without options, and validation will subsequently fail (since it uses those same options to validate input). Alternatively, you can use ModelMultipleChoiceFilter, which requires a queryset to construct its choices from. Note that the queryset/choice handling is builtin behavior of the underlying form field, and isn't specific to django-filter.
For the latter option, there are more details in the docs linked above, but it's worth mentioning that it renders a text input and expects a querystring like ?a=1,2 instead of ?a=1&a=2.

Laravel PDF generation with Graph and send it with Email

I tried to find it on StackOverflow and also tried to google it, but could not find any relevant answer.
I want to send monthly reports to the user of Laravel application with a PDF that contain a graph/chart.
This is what that is already done
Created a route, lets say
Route::get('/print/', 'PrintController#report');
In printController created a report function that is getting all the necessary data from the DB and returning a view with user data
return view::make('monthly_report', $user_data);
In monthly_report view, get all the user data, show the view and create a chart with the data. The chart is created with Charts.js. it is in a canvas.
Send the generated chart as image to the server with Ajax. For example
var canvas = document.getElementById("myChart"), // Get your canvas
imgdata = canvas.toDataURL();
file_name = "<?php echo $chart_file_name; ?>"; //created with userId and date
//send it to server
$.ajax({
method: "POST",
url: "save",
data: {
data: imgdata,
file_name: file_name,
_token: token,
}
});
Created a save route
Route::post('print/save', 'PrintController#saveChart');
In print controller, saveChart function, save the chart
$data = base64_decode($data);
//save chart on server
file_put_contents("Charts/".$fileName, $data);
Then create a PDF report by using another view monthly_report2, that is also in saveChart function. The view monthly_report2 does not use any JavaScript and use the chart image that was generated by monthly_report, in number 6.
$pdf = \PDF::loadView('monthly_report2', $cll_data);
file_put_contents("reports/".$pdf_name, $pdf->output());
It save the generated PDF on server. So far so good.
To send these PDF reports to the users by e-mail, I will created a schedule/crone job that will be run on a specific date, monthly and will send the e-mails with PDF reports as attachments.
I skip some details for clarity, please ask, if you need more information.
Thank you for reading so far, now I have two questions
The way I am doing is good or it can be improve?
We want all this process automatically (generating reports and sending by email). To generate the PDF's, monthly_report view must be loaded? so that it generate the Chart and send it to the server. Can we schedule it also, so that it generate the pdf reports automatically?, If no, is there any other way to do it?
Kind of a big question, but I'll try to answer
I think it's good. I'm not a big fan of using JavaScript to create charts, but that's me. You obviously know what you're doing and PDF generation is in my experience a "If it works, please don't break it" functionality.
I think this might be more difficult. Since you're using JavaScript to create charts, you need some kind of engine (NodeJS comes to mind) to parse the JavaScript and actually create your charts without opening a browser and doing it manually. (This is why I don't like using JavaScript to create charts). You could take a look at tutorials like this one to get an idea of how to render your charts serverside.
After that, you can take a look at the Laravel task scheduler (provided you're on Laravel 5, a community package exists for Laravel 4). You can schedule existing and custom-made commands to be executed. In pseudo-code, a PDF generation command could look like this:
public function createAndSendCharts() {
// 1. Get necessary user data
// 2. Create your charts
// 3. Save your charts
// 4. Create email with charts
// 5. Send your email
}
You could then add that function to your Task Scheduler
$schedule->command('send:charts')
->monthly();
Hope this was of some help. All in all, you're doing fine, but the choice for ChartJS has some consequences if you want to automate the whole process. Nothing really special, tons of tutorials exist for this situation :)

How to populate one dropdown from the other in django dynamically using AJAX/DAJAX/DAJAXICE/Simple Javascript?

I have searched enough of the examples but couldn't get the satisfactory result. Please explain with all the necessary code. I am very poor at AJAX. I tried to use DAJAXICE in my code and got little success but didn't work with passing parameters.
I am using Django 1.6 Dajaxice 0.7 Dajax 0.9.
Any way you feel the easiest is okay but please explain with all the code.
TIA.
If all you need is a simple Django view to fetch some data with AJAX, take a look at django-braces AjaxResponseMixin. Below is a code sample which returns list of objects ids and their names:
from django.views.generic import View
from braces import views
class SomeView(views.JSONResponseMixin, views.AjaxResponseMixin, View):
def get_ajax(self, request, *args, **kwargs):
my_objects = MyObject.objects.all()
json_dict = {
'ids': [x.id for x in my_objects],
'names': [x.name for x in my_objects]
}
return self.render_json_response(json_dict)
Then use jQuery ajax to make the query from your template and populate your fields.
If you're not familiar with Class Based Views, your url for this view could be:
url('^objects/(?P<some_id>[0-9]+)/$', SomeView.as_view())
then in get_ajax you can access self.kwargs['some_id'] to filter objects.

Change url of angular-ui-router without reloading page

I'd like for changes in the URL to drive my application, and for changes in the application to change the URL, but not actually change state.
I have a route like this. The country/city example is a bit contrived, hopefully that doesn't confuse things. The relationship in the real application is somewhat hierarchical. Child views don't seem a fit though because there's no need for nested views.
$stateProvider.state( 'viewMap', {
url: '/viewMap/:country/:city',
templateUrl: 'pages/viewMap/viewMap.html',
controller: 'ViewMapController'
};
In ViewMapController, I can construct the page based on $stateParams.country and .city. As these values change, my application reacts and I want the url to stay in sync. I don't want to reload the whole page, however. I just want to update the url and push a history state on to the stack.
I understand I could manually construct a string:
updateUrl = function() {
window.location.hash = '#/viewMap/'+ $stateParams.country +'/'+ $stateParams.city
}
This feels fragile, as the way I build the string is separate from the way the framework parses it. I would prefer for the framework to build me a string based on the current params, but $state.href('.') describes the current route, which doesn't include $stateParams that haven't yet been activated/navigated to.
I've also looked at reloadOnSearch, but I think it only applies to query params.
Is there a better way to model this? It feels like I'm fighting the framework over something simple.
You can pass state params to $state.href function to get the complete URL
$state.href('.', $stateParams)
To generate arbitrary urls you can pass non-current params and/or configuration:
$state.href('.', {country:'usa',city:'sf'}, {absolute:true})

Request for several responses

I would like to create a web application.
There are cases, when a user's request would result in refreshing the content in 2-3 or sometimes even more containers. The cleanest way would be to run the requests one after the other in a sequence and handle the results one by one. I would like to have only one request if it is possible, and collecting all the results for the responses.
Eg.: let's say, there is a main container (M), and some other (smaller) containers (A, B, C, etc.)
The simple way would be:
request main function from server for M, show it in M container
fetch some other content from server dedicated for A_container, show it in A_container
fetch some other content from server dedicated for B_container, show it in B_container
fetch some other content from server dedicated for C_container, show it in C_container
Depending on the main function requested by the user, just some of the containers have to refresh it's content, not all of them.
I would like to minimise the number of requests. Actually minimise it to one. Of course, it could be done by Json, or XML.
I would like to collect all the responses from the server, encapsulate them (A_container:"this is content for A_container", C_container: "Other content for C_container"), and send it back to the client, where the client would unpack it, and regarding to the content, it would delegate each of them to the appropriate container.
My question is, that how would you do it, when you know, that the returned data is very variable: in some cases it might contain even html elements, quotes, double quotes, etc. If I am not mistaken, in some special cases this could screw up Json and xml as well.
My idea was to divide the different contents by special separators (for now just for an easy example let's use xxx, and yyy). It is a very uggly solution, but you cannot screw up the content for sure, if the separators are unique enough.
The previous Json-like solution would look like this:
"A_containeryyythis is content for A_containerxxxC_containeryyyOther content for C_container"
Then on the client side split the code first by xxx, which would result in this case in two array elements (strings), what are going to be split again by yyy. The first element would give the container's id, the second one the content for it. After this the last step would be walking through the new arrays, and display the result in the appropriate containers.
Is there anybody who would suggest a nicer way for this, or who could show a safe way to do it in Json, or XML, etc?
The previous Json-like solution would look like this: "A_containeryyythis is content for A_containerxxxC_containeryyyOther content for C_container"
THat woul seem more like a "text/plain" response from the server that you would handle via a javascript split. What you would really want to do is return a json object from the server, e.g.
object = {'A container content','etc','etc','etc'}
Then evaluate that using javascript from the client side using eval(object). From there I would populate each one of your "containers".
Format your request using XML:
<response>
<m>Content</m>
<a>Content</a>
<b>Content</b>
<c>Content</c>
</response>
Then parse the XML in your XMLHttpRequest callback:
var xmldoc = req.responseXML;
var root = xmldoc.getElementsByTagName('response').item(0);
var contentm = root.getElementsByTagName('m');
var contenta = root.getElementsByTagName('a');
var contentb = root.getElementsByTagName('b');
var contentc = root.getElementsByTagName('c');
if (contentm) {
/* Update Container M */
}
if (contenta) {
/* Update Container A */
}
if (contentb) {
/* Update Container B */
}
if (contentc) {
/* Update Container C */
}

Resources