| 
									
										
										
										
											2010-04-19 22:01:14 +08:00
										 |  |  | AJAX with jQuery
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | ================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | `jQuery`_ is a small JavaScript library commonly used to simplify working
 | 
					
						
							|  |  |  | with the DOM and JavaScript in general.  It is the perfect tool to make
 | 
					
						
							|  |  |  | web applications more dynamic by exchanging JSON between server and
 | 
					
						
							|  |  |  | client.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | JSON itself is a very lightweight transport format, very similar to how
 | 
					
						
							|  |  |  | Python primitives (numbers, strings, dicts and lists) look like which is
 | 
					
						
							|  |  |  | widely supported and very easy to parse.  It became popular a few years
 | 
					
						
							|  |  |  | ago and quickly replaced XML as transport format in web applications.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-24 06:37:51 +08:00
										 |  |  | .. _jQuery: https://jquery.com/
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Loading jQuery
 | 
					
						
							|  |  |  | --------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | In order to use jQuery, you have to download it first and place it in the
 | 
					
						
							|  |  |  | static folder of your application and then ensure it's loaded.  Ideally
 | 
					
						
							|  |  |  | you have a layout template that is used for all pages where you just have
 | 
					
						
							| 
									
										
										
										
											2014-11-05 12:27:25 +08:00
										 |  |  | to add a script statement to the bottom of your ``<body>`` to load jQuery:
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .. sourcecode:: html
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    <script type=text/javascript src="{{
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  |      url_for('static', filename='jquery.js') }}"></script>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Another method is using Google's `AJAX Libraries API
 | 
					
						
							| 
									
										
										
										
											2019-06-24 06:37:51 +08:00
										 |  |  | <https://developers.google.com/speed/libraries/>`_ to load jQuery:
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .. sourcecode:: html
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-27 07:56:05 +08:00
										 |  |  |     <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
 | 
					
						
							| 
									
										
										
										
											2011-06-21 05:51:30 +08:00
										 |  |  |     <script>window.jQuery || document.write('<script src="{{
 | 
					
						
							|  |  |  |       url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-06-21 05:51:30 +08:00
										 |  |  | In this case you have to put jQuery into your static folder as a fallback, but it will
 | 
					
						
							|  |  |  | first try to load it directly from Google. This has the advantage that your
 | 
					
						
							| 
									
										
										
										
											2010-07-18 16:30:58 +08:00
										 |  |  | website will probably load faster for users if they went to at least one
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | other website before using the same jQuery version from Google because it
 | 
					
						
							| 
									
										
										
										
											2011-06-21 05:51:30 +08:00
										 |  |  | will already be in the browser cache.
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Where is My Site?
 | 
					
						
							|  |  |  | -----------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Do you know where your application is?  If you are developing the answer
 | 
					
						
							|  |  |  | is quite simple: it's on localhost port something and directly on the root
 | 
					
						
							|  |  |  | of that server.  But what if you later decide to move your application to
 | 
					
						
							|  |  |  | a different location?  For example to ``http://example.com/myapp``?  On
 | 
					
						
							|  |  |  | the server side this never was a problem because we were using the handy
 | 
					
						
							| 
									
										
										
										
											2010-08-03 00:07:10 +08:00
										 |  |  | :func:`~flask.url_for` function that could answer that question for
 | 
					
						
							|  |  |  | us, but if we are using jQuery we should not hardcode the path to
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | the application but make that dynamic, so how can we do that?
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | A simple method would be to add a script tag to our page that sets a
 | 
					
						
							|  |  |  | global variable to the prefix to the root of the application.  Something
 | 
					
						
							|  |  |  | like this:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. sourcecode:: html+jinja
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |    <script type=text/javascript>
 | 
					
						
							|  |  |  |      $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
 | 
					
						
							|  |  |  |    </script>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-03 19:25:08 +08:00
										 |  |  | The ``|safe`` is necessary in Flask before 0.10 so that Jinja does not
 | 
					
						
							|  |  |  | escape the JSON encoded string with HTML rules.  Usually this would be
 | 
					
						
							| 
									
										
										
										
											2014-11-05 12:56:03 +08:00
										 |  |  | necessary, but we are inside a ``script`` block here where different rules
 | 
					
						
							| 
									
										
										
										
											2013-06-03 19:25:08 +08:00
										 |  |  | apply.
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .. admonition:: Information for Pros
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-05 12:56:03 +08:00
										 |  |  |    In HTML the ``script`` tag is declared ``CDATA`` which means that entities
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:39:07 +08:00
										 |  |  |    will not be parsed.  Everything until ``</script>`` is handled as script.
 | 
					
						
							|  |  |  |    This also means that there must never be any ``</`` between the script
 | 
					
						
							| 
									
										
										
										
											2010-06-05 13:49:04 +08:00
										 |  |  |    tags.  ``|tojson`` is kind enough to do the right thing here and
 | 
					
						
							| 
									
										
										
										
											2010-05-28 03:17:25 +08:00
										 |  |  |    escape slashes for you (``{{ "</script>"|tojson|safe }}`` is rendered as
 | 
					
						
							| 
									
										
										
										
											2010-04-20 00:51:04 +08:00
										 |  |  |    ``"<\/script>"``).
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-03 19:25:08 +08:00
										 |  |  |    In Flask 0.10 it goes a step further and escapes all HTML tags with
 | 
					
						
							|  |  |  |    unicode escapes.  This makes it possible for Flask to automatically
 | 
					
						
							|  |  |  |    mark the result as HTML safe.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | JSON View Functions
 | 
					
						
							|  |  |  | -------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now let's create a server side function that accepts two URL arguments of
 | 
					
						
							|  |  |  | numbers which should be added together and then sent back to the
 | 
					
						
							|  |  |  | application in a JSON object.  This is a really ridiculous example and is
 | 
					
						
							|  |  |  | something you usually would do on the client side alone, but a simple
 | 
					
						
							| 
									
										
										
										
											2010-04-20 19:01:10 +08:00
										 |  |  | example that shows how you would use jQuery and Flask nonetheless::
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     from flask import Flask, jsonify, render_template, request
 | 
					
						
							|  |  |  |     app = Flask(__name__)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @app.route('/_add_numbers')
 | 
					
						
							|  |  |  |     def add_numbers():
 | 
					
						
							|  |  |  |         a = request.args.get('a', 0, type=int)
 | 
					
						
							|  |  |  |         b = request.args.get('b', 0, type=int)
 | 
					
						
							|  |  |  |         return jsonify(result=a + b)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @app.route('/')
 | 
					
						
							|  |  |  |     def index():
 | 
					
						
							|  |  |  |         return render_template('index.html')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As you can see I also added an `index` method here that renders a
 | 
					
						
							| 
									
										
										
										
											2018-10-27 22:27:45 +08:00
										 |  |  | template.  This template will load jQuery as above and have a little form where
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | we can add two numbers and a link to trigger the function on the server
 | 
					
						
							|  |  |  | side.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-03-14 08:48:19 +08:00
										 |  |  | Note that we are using the :meth:`~werkzeug.datastructures.MultiDict.get` method here
 | 
					
						
							| 
									
										
										
										
											2010-04-20 19:01:10 +08:00
										 |  |  | which will never fail.  If the key is missing a default value (here ``0``)
 | 
					
						
							|  |  |  | is returned.  Furthermore it can convert values to a specific type (like
 | 
					
						
							| 
									
										
										
										
											2010-04-21 00:40:58 +08:00
										 |  |  | in our case `int`).  This is especially handy for code that is
 | 
					
						
							| 
									
										
										
										
											2010-04-20 19:01:10 +08:00
										 |  |  | triggered by a script (APIs, JavaScript etc.) because you don't need
 | 
					
						
							|  |  |  | special error reporting in that case.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | The HTML
 | 
					
						
							|  |  |  | --------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:45:22 +08:00
										 |  |  | Your index.html template either has to extend a :file:`layout.html` template with
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | jQuery loaded and the `$SCRIPT_ROOT` variable set, or do that on the top.
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:45:22 +08:00
										 |  |  | Here's the HTML code needed for our little application (:file:`index.html`).
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | Notice that we also drop the script directly into the HTML here.  It is
 | 
					
						
							|  |  |  | usually a better idea to have that in a separate script file:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. sourcecode:: html
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     <script type=text/javascript>
 | 
					
						
							|  |  |  |       $(function() {
 | 
					
						
							|  |  |  |         $('a#calculate').bind('click', function() {
 | 
					
						
							|  |  |  |           $.getJSON($SCRIPT_ROOT + '/_add_numbers', {
 | 
					
						
							|  |  |  |             a: $('input[name="a"]').val(),
 | 
					
						
							|  |  |  |             b: $('input[name="b"]').val()
 | 
					
						
							|  |  |  |           }, function(data) {
 | 
					
						
							|  |  |  |             $("#result").text(data.result);
 | 
					
						
							|  |  |  |           });
 | 
					
						
							|  |  |  |           return false;
 | 
					
						
							|  |  |  |         });
 | 
					
						
							|  |  |  |       });
 | 
					
						
							|  |  |  |     </script>
 | 
					
						
							|  |  |  |     <h1>jQuery Example</h1>
 | 
					
						
							|  |  |  |     <p><input type=text size=5 name=a> +
 | 
					
						
							|  |  |  |        <input type=text size=5 name=b> =
 | 
					
						
							|  |  |  |        <span id=result>?</span>
 | 
					
						
							|  |  |  |     <p><a href=# id=calculate>calculate server side</a>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-08 08:42:06 +08:00
										 |  |  | I won't go into detail here about how jQuery works, just a very quick
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | explanation of the little bit of code above:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1. ``$(function() { ... })`` specifies code that should run once the
 | 
					
						
							|  |  |  |    browser is done loading the basic parts of the page.
 | 
					
						
							| 
									
										
										
										
											2010-06-05 15:06:14 +08:00
										 |  |  | 2. ``$('selector')`` selects an element and lets you operate on it.
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  | 3. ``element.bind('event', func)`` specifies a function that should run
 | 
					
						
							|  |  |  |    when the user clicked on the element.  If that function returns
 | 
					
						
							| 
									
										
										
										
											2012-04-19 23:51:38 +08:00
										 |  |  |    `false`, the default behavior will not kick in (in this case, navigate
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  |    to the `#` URL).
 | 
					
						
							| 
									
										
										
										
											2014-11-05 11:13:01 +08:00
										 |  |  | 4. ``$.getJSON(url, data, func)`` sends a ``GET`` request to `url` and will
 | 
					
						
							| 
									
										
										
										
											2010-04-19 21:59:16 +08:00
										 |  |  |    send the contents of the `data` object as query parameters.  Once the
 | 
					
						
							|  |  |  |    data arrived, it will call the given function with the return value as
 | 
					
						
							|  |  |  |    argument.  Note that we can use the `$SCRIPT_ROOT` variable here that
 | 
					
						
							|  |  |  |    we set earlier.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-13 02:06:02 +08:00
										 |  |  | Check out the :gh:`example source <examples/javascript>` for a full
 | 
					
						
							| 
									
										
										
										
											2018-04-13 03:17:14 +08:00
										 |  |  | application demonstrating the code on this page, as well as the same
 | 
					
						
							| 
									
										
										
										
											2018-04-13 02:06:02 +08:00
										 |  |  | thing using ``XMLHttpRequest`` and ``fetch``.
 |