librelist archives

« back to archive

Re: Flask: pass JS variable (Ajax) to Jinja2

Re: Flask: pass JS variable (Ajax) to Jinja2

From:
Nikos Skalis
Date:
2014-11-16 @ 20:32
> Hi All,
> 
> I am trying to write my first Flask application.
> The issue I am facing is as follows :
> 
> In HTML, I do a call to some JS code (using Bootbox) with Ajax, the 
argument taken is passed to Python where it constructs a JSON variable.
> In order to achieve this, there 2 ways, as far as I know :
> [1] use render_template and pass the JSON variable back to the template
> [2] return the JSON variable to the JS code, _and_ pass it over to HTML
> The option [1] I think is not doable because the Ajax call expects a 
JSON so I cannot use the render_template method (if I change the dataType 
to html I get Error 500 that I cannot resolve).
> Option [2], I don’t know how to implement that.

I realized that I can call render_template while I have contentType as JSON,
but I don’t know to access the JSON variable.

> 
> The workaround, and how it works at the moment is using, Sessions.
> 
> But ideally I would like to avoid that for the JSON variable that I am 
using, and manage to pass it as an argument.
> Looking forward to hearing from you and show me the right way to implement it.
> Many Thanks.
> 
> HTML
> ...
> <p><a id="signin_session" class="bb-trigger btn btn-primary btn-lg 
btn-block">Sign In</a></p>
> …
> 
> JS/Ajax
> ...
> 		bootbox.prompt("<strong>Email address</strong><br>Please enter the 
email address where the report should be send to : ", 
function(email_address)  {
> 				if (email_address)	{ 
> 
> 					formulate			= {'email_address': email_address} ;
> 					$.ajax({
> 						url: 			"/jcertify/session-report/",
> 						data: 			JSON.stringify(formulate,null), // {'email_address': 
email_address},
> 						type: 			"POST",
> 						contentType: 	"application/json;charset=UTF-8",
> 						success: 		function(response) { 
> 							// var etc = $.parseJSON(response); console.log(etc) ; 
> 							window.location.reload() ;
> 							console.log(response) ;
> 						},
> 						error: 			function(error) { console.log(error) ; }
> 					});
> …
> 
> Python
> ...
> session['report_2_email'] 	= request.json['email_address']
> 	session['test_info']		= META['tcase']
> 	data 	= jsonify({'email_address': request.json['email_address'], 
'testcases':META['tcase']})
> 	#	return 	render_template("jcertify.html", test_info=data)
> 	return 	data
> …
> 
> HTML
> …
> {% if session['report_2_email'] %}
>      <div class="testcase">
>        <table class="table table-hover">
>        <thead><tr><th>#</th><th>Testcase</th><th>Username</th></tr></thead>
>        <tbody>
>          {% set step = 0 %}
>          {% for tcase in session['test_info'] %}
>          <tr><td>{{ step }}</td><td><p class="text-uppercase"><code>{{ 
tcase }}</code></p></td><td><i>{{ session['report_2_email'] 
}}</i></td></tr>
>          {% set step = step + 1 %}
>          {% endfor %}
>        </tbody>
>        </table>
>      </div>
>      {% endif %}
> ...
> 
> Kind Regards,
> Nikos

Re: [flask] Re: Flask: pass JS variable (Ajax) to Jinja2

From:
Matt Gushee
Date:
2014-11-17 @ 00:08
Hi, Nikos--

First of all, a caveat: I am pretty new to Flask. I've built one
production site using it, but it was a very simple one, with no
interactive features. But I enjoy solving problems, so I'll take a
stab at yours!

On Sun, Nov 16, 2014 at 1:32 PM, Nikos Skalis
<nskalis.amsterdam@gmail.com> wrote:

>> In HTML, I do a call to some JS code (using Bootbox) with Ajax, the 
argument taken is passed to Python where it constructs a JSON variable.

This is not a very clear statement. But I think you mean that the AJAX
request is received by the Flask (Python) application. Yes?

>> In order to achieve this, there 2 ways, as far as I know :
>> [1] use render_template and pass the JSON variable back to the template

If I understand correctly what you mean here, this is not a sensible
approach. See below.

>> [2] return the JSON variable to the JS code, _and_ pass it over to HTML

What does "pass it over to HTML" mean?

> I realized that I can call render_template while I have contentType as JSON,
> but I don’t know to access the JSON variable.

I don't think this is really a Flask problem. Based on your sample
code, it seems like you are trying to mix two different approaches in
a way that cannot work.

>> JS/Ajax

>>                                       $.ajax({


... OK, so your client-side code is generating an AJAX request ...

>>                                               success:                
function(response) {
>>                                                       // var etc = 
$.parseJSON(response); console.log(etc) ;
>>                                                       
window.location.reload() ;

... but now you are requesting a new (HTML) page from the server?

Maybe this is some kind of advanced hack that I haven't learned yet,
but as I understand it, the main point of AJAX is to not request a new
page from the server. In any case:

* If you really want to request a whole new page, then there is no
point in generating a JSON response in your Flask app. Just generate a
normal HTML page.

* If you really want to do AJAX, then in your Flask app, just call
flask.jsonify(), and return the data. No need for a template, and no
need to set the Content-Type header. In that case, you will need
client-side (JS) code to show the results in your page, and you should
not call window.location.reload(). Of course, the client-side code is
outside the scope of this mailing list (and I'm not familiar with
bootbox/bootstrap anyway).

Either approach is valid; I can't tell you which is better for your application.

Hope that helps!

--
Matt Gushee

Re: [flask] Re: Flask: pass JS variable (Ajax) to Jinja2

From:
Nikos Skalis
Date:
2014-11-17 @ 06:10
Thanks Michael for your time for looking into this.
More specifically,

I use jsonify to return the data (JSON) in Python.
the location.reload() equals to render_template

One thing is what I do not know :
	[1] why render_template produces a 500 error ?

I have attached the .js. and the .py file

Re: [flask] Re: Flask: pass JS variable (Ajax) to Jinja2

From:
Matt Gushee
Date:
2014-11-17 @ 07:52
Hi, Nikos--

On Sun, Nov 16, 2014 at 11:10 PM, Nikos Skalis
<nskalis.amsterdam@gmail.com> wrote:

> One thing is what I do not know :
>         [1] why render_template produces a 500 error ?

If you are referring to this case ...
> data     = jsonify({'email_address': request.json['email_address'], 
'testcases':META['tcase']})
> return     render_template("jcertify.html", test_info=data)

... I suppose it is because 'data' is a Response object. Haven't tried
it myself. I don't think it would work - and in any case this is
exactly what I was talking about before. If you are generating an HTML
page, as the above code does, there is no reason to convert the data
to JSON. Just pass it to render_template() as a dictionary. Also, the
template you posted earlier refers to a 'session' variable, but you
are passing it a 'test_info' variable; it should be pretty obvious
that the variable names in the template need to match the names given
to render_template(), right?

As for your final question, how to access 'test_info' in Jinja2, it
should be simple: as long as you pass a valid 'test_info' variable in
the call to render_template(), and the template refers to 'test_info',
I don't see why it wouldn't work. If it doesn't, you might need some
unit tests to figure it out.

--
Matt Gushee

Re: [flask] Flask: pass JS variable (Ajax) to Jinja2

From:
Nikos Skalis
Date:
2014-11-17 @ 06:11
> 
> Thanks Matt for your time for looking into this.
> More specifically,
> 
> I use jsonify to return the data (JSON) in Python.
> the location.reload() equals to render_template
> 
> One thing is what I do not know :
> 	[1] why render_template produces a 500 error ?
> 
> I have attached the .js. and the .py file

Re: [flask] Flask: pass JS variable (Ajax) to Jinja2

From:
Nikos Skalis
Date:
2014-11-17 @ 06:36
OK, I made it working with render_template
The thing missing was that I had to use 
	document.write(response) ;

So the now the issue is almost solved except from the fact that I don’t 
know how to access the test_info variable in Jinja2 ?

> On Nov 17, 2014, at 7:11 AM, Nikos Skalis <nskalis.amsterdam@gmail.com> wrote:
> 
>> 
>> Thanks Matt for your time for looking into this.
>> More specifically,
>> 
>> I use jsonify to return the data (JSON) in Python.
>> the location.reload() equals to render_template
>> 
>> One thing is what I do not know :
>> 	[1] why render_template produces a 500 error ?
>> 
>> I have attached the .js. and the .py file
> <session.js><lablytics.py>
>> 
>>> On Nov 17, 2014, at 1:08 AM, Matt Gushee <matt@salixmedia.com> wrote:
>>> 
>>> Hi, Nikos--
>>> 
>>> First of all, a caveat: I am pretty new to Flask. I've built one
>>> production site using it, but it was a very simple one, with no
>>> interactive features. But I enjoy solving problems, so I'll take a
>>> stab at yours!
>>> 
>>> On Sun, Nov 16, 2014 at 1:32 PM, Nikos Skalis
>>> <nskalis.amsterdam@gmail.com> wrote:
>>> 
>>>>> In HTML, I do a call to some JS code (using Bootbox) with Ajax, the 
argument taken is passed to Python where it constructs a JSON variable.
>>> 
>>> This is not a very clear statement. But I think you mean that the AJAX
>>> request is received by the Flask (Python) application. Yes?
>>> 
>>>>> In order to achieve this, there 2 ways, as far as I know :
>>>>> [1] use render_template and pass the JSON variable back to the template
>>> 
>>> If I understand correctly what you mean here, this is not a sensible
>>> approach. See below.
>>> 
>>>>> [2] return the JSON variable to the JS code, _and_ pass it over to HTML
>>> 
>>> What does "pass it over to HTML" mean?
>>> 
>>>> I realized that I can call render_template while I have contentType as JSON,
>>>> but I don’t know to access the JSON variable.
>>> 
>>> I don't think this is really a Flask problem. Based on your sample
>>> code, it seems like you are trying to mix two different approaches in
>>> a way that cannot work.
>>> 
>>>>> JS/Ajax
>>> 
>>>>>                                    $.ajax({
>>> 
>>> 
>>> ... OK, so your client-side code is generating an AJAX request ...
>>> 
>>>>>                                            success:                
function(response) {
>>>>>                                                    // var etc = 
$.parseJSON(response); console.log(etc) ;
>>>>>                                                    
window.location.reload() ;
>>> 
>>> ... but now you are requesting a new (HTML) page from the server?
>>> 
>>> Maybe this is some kind of advanced hack that I haven't learned yet,
>>> but as I understand it, the main point of AJAX is to not request a new
>>> page from the server. In any case:
>>> 
>>> * If you really want to request a whole new page, then there is no
>>> point in generating a JSON response in your Flask app. Just generate a
>>> normal HTML page.
>>> 
>>> * If you really want to do AJAX, then in your Flask app, just call
>>> flask.jsonify(), and return the data. No need for a template, and no
>>> need to set the Content-Type header. In that case, you will need
>>> client-side (JS) code to show the results in your page, and you should
>>> not call window.location.reload(). Of course, the client-side code is
>>> outside the scope of this mailing list (and I'm not familiar with
>>> bootbox/bootstrap anyway).
>>> 
>>> Either approach is valid; I can't tell you which is better for your 
application.
>>> 
>>> Hope that helps!
>>> 
>>> --
>>> Matt Gushee
>> 
>