• en
  • Language: ru
  • Documentation version: 1.1.x

AJAX с jQuery

jQuery - это небольшая библиотека JavaScript, широко используемая для упрощения работы с DOM и JavaScript в целом. Это идеальный инструмент для того, чтобы сделать веб-приложения более динамичными за счет обмена JSON между сервером и клиентом.

Сам по себе JSON - это очень легкий транспортный формат, очень похожий на то, как выглядят примитивы Python (числа, строки, дикты и списки), который широко поддерживается и очень легко разбирается. Он стал популярным несколько лет назад и быстро заменил XML в качестве транспортного формата в веб-приложениях.

Загрузка jQuery

Для того чтобы использовать jQuery, вы должны сначала загрузить его и поместить в папку static вашего приложения, а затем убедиться, что он загружен. В идеале у вас есть шаблон макета, который используется для всех страниц, где вам просто нужно добавить оператор сценария в нижнюю часть <body> для загрузки jQuery:

<script type=text/javascript src="{{
  url_for('static', filename='jquery.js') }}"></script>

Другой метод - использование AJAX Libraries API Google для загрузки jQuery:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="{{
  url_for('static', filename='jquery.js') }}">\x3C/script>')</script>

В этом случае вам придется поместить jQuery в папку static в качестве запасного варианта, но сначала он попытается загрузить его непосредственно из Google. Преимущество этого способа заключается в том, что ваш сайт, вероятно, будет загружаться быстрее для пользователей, если они зашли хотя бы на один другой сайт, прежде чем использовать ту же версию jQuery из Google, потому что она уже будет в кэше браузера.

Где находится мой сайт?

Знаете ли вы, где находится ваше приложение? Если вы занимаетесь разработкой, то ответ довольно прост: оно находится на каком-то порту localhost и непосредственно в корне этого сервера. Но что если вы позже решите переместить свое приложение в другое место? Например, на http://example.com/myapp? На стороне сервера это никогда не было проблемой, потому что мы использовали удобную функцию url_for(), которая могла ответить на этот вопрос за нас, но если мы используем jQuery, мы не должны жестко кодировать путь к приложению, а сделать его динамическим, так как же это сделать?

Простой метод заключается в том, чтобы добавить тег script к нашей странице, который устанавливает глобальную переменную на префикс корня приложения. Что-то вроде этого:

<script type=text/javascript>
  $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
</script>

Символ |safe необходим во Flask до версии 0.10, чтобы Jinja не экранировала строку, закодированную в JSON, с помощью правил HTML. Обычно это было бы необходимо, но мы находимся внутри блока script, где действуют другие правила.

Информация для профессионалов

В HTML тег script объявляется CDATA, что означает, что сущности не будут разобраны. Все до </script> обрабатывается как сценарий. Это также означает, что между тегами script никогда не должно быть никаких </. |tojson достаточно любезен, чтобы сделать правильную вещь здесь и экранировать слеши для вас ({{ "</script>"|tojson|safe }} отображается как "<\/script>").

В версии Flask 0.10 он идет дальше и экранирует все HTML-теги эскейпами юникода. Это позволяет Flask автоматически помечать результат как HTML-безопасный.

Функции представления JSON

Теперь давайте создадим функцию на стороне сервера, которая принимает два аргумента URL с числами, которые должны быть сложены вместе и затем отправлены обратно в приложение в объекте JSON. Это действительно нелепый пример, который обычно делают только на стороне клиента, но простой пример, который показывает, как можно использовать jQuery и Flask, тем не менее:

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')

Как вы можете видеть, я также добавил метод index, который отображает шаблон. Этот шаблон загрузит jQuery, как указано выше, и будет иметь небольшую форму, в которую мы можем добавить два числа и ссылку для запуска функции на стороне сервера.

Обратите внимание, что здесь мы используем метод get(), который никогда не даст сбоя. Если ключ отсутствует, возвращается значение по умолчанию (здесь 0). Кроме того, метод может преобразовывать значения к определенному типу (как в нашем случае int). Это особенно удобно для кода, который запускается скриптом (API, JavaScript и т.д.), потому что в этом случае вам не нужно специальное сообщение об ошибках.

HTML

Ваш шаблон index.html должен либо расширять шаблон layout.html с загруженным jQuery и установленной переменной $SCRIPT_ROOT, либо делать это сверху. Вот HTML-код, необходимый для нашего маленького приложения (index.html). Обратите внимание, что здесь мы также вставляем скрипт непосредственно в 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>

Я не буду вдаваться в подробности о том, как работает jQuery, просто очень быстро объясню небольшой кусочек кода выше:

  1. $(function() { ... }) определяет код, который должен выполняться после того, как браузер закончит загрузку основных частей страницы.

  2. $('selector') выбирает элемент и позволяет оперировать с ним.

  3. element.bind('event', func) задает функцию, которая должна выполняться, когда пользователь нажимает на элемент. Если эта функция возвращает false, то поведение по умолчанию не сработает (в данном случае переход на URL #).

  4. $.getJSON(url, data, func) отправляет запрос GET на url и передает содержимое объекта data в качестве параметров запроса. После получения данных будет вызвана заданная функция с возвращаемым значением в качестве аргумента. Обратите внимание, что здесь мы можем использовать переменную $SCRIPT_ROOT, которую мы задали ранее.

Посмотрите example source для полного приложения, демонстрирующего код на этой странице, а также то же самое с использованием XMLHttpRequest и fetch.