Введение в Django

Улучшение пользовательского интерфейса с помощью Ajax

Разбить на страницы
Показывать лекцию целиком

Цель лекции: рассмотреть основы технологии AJAX, познакомиться с понятием формы, рассмотреть основные типы виджетов, создать страницу поиска твитов, познакомиться с методами jQuery, добавить автодополнение хэштегов при отправке твита.

Ключевые термины: AJAX, CSS, HTML, jQuery, форма, фреймворк, твит, хештег, имплементация, элемент, запрос, поиск, метод, атрибут, приложение.

Появление AJAX стало важной вехой в истории Веб 2.0. AJAX — это группа технологий, что позволяет разработчикам создавать интерактивные, с большими возможностями веб-приложения. Большинство из этих технологий были доступны за многие годы до появления самого AJAX. Однако появление AJAX представляет переход Web от статических страниц, которые необходимо обновлять всякий раз, когда происходил обмен данными к динамическим, гибким и интерактивным пользовательским интерфейсам.

Так как наш проект является приложением Веб 2.0, оно должно быть более нацелено на пользователей. Успех нашего приложения зависит от получения пользователем возможности размещать и обмениваться контентом на нем. Таким образом, пользовательский интерфейс нашего приложения является одной из наших основных проблем. Эта лекция улучшит интерфейс нашего приложения с помощью описания возможностей AJAX, что сделает его более удобным для пользователей и интерактивным.

AJAX и его преимущества

AJAX, которая расшифовывается как Asynchronous JavaScript and XML (Асинхронный JavaScript и XML), состоит из следующих технологий:

  • HTML и CSS для структурирования информации и придания стилей
  • JavaScript для динамического доступа и манипулирования информацией
  • Объект XMLHttpRequest, который представляет собой объект, предоставляемый современнми браузерами для обмена данными с сервером без перезагрузки текущей веб-страницы
  • Формат для передачи данных между клиентом и сервером
  • Иногда используется XML, но это может быть в HTML, обычном тексте или формате на основе JavaScript, называемом JSON.

    AJAX технологии позволяют кодировать обмен данными на клиентской стороне с сервером за кулисами, без перезагрузки всей страницы каждый раз, когда пользователь делает запрос. С помощью AJAX, веб-разработчик может увеличить интерактивность и удобство использования ' веб-страниц.

    AJAX обеспечивает следующие преимущества при имплементации в правильных местах:

  • Улучшение опыта пользователя: пользователь с AJAX может сделать много без обновления страницы, которая делает веб-приложения ближе к обычным настольным приложениям
  • Лучшая производительность: путем обмена только требуемых данных внутри сервера, AJAX сохраняет пропускную способность и увеличивает скорость приложений
  • Существует множество примеров веб-приложений, использующих AJAX: карты Google и Gmail, возможно, два наиболее известных примера. В самом деле, эти два приложения играют важную роль в распространении использования AJAX из-за того успеха, которыми они пользуются. Что отличает Gmail от других почтовых сервисов, это его пользовательский интерфейс, который позволяет пользователям интерактивно управлять электронной почтой, не дожидаясь перезагрузки страницы после каждого действия, и это создает лучший пользовательский опыт и позволяет Gmail чувствовать себя отзывчивым и многофункциональным приложением, нежели простой веб-сайт.

    В этой лекции объясняется, как использовать AJAX с Django, с тем чтобы сделать приложения более гибким и удобным для пользователей. Мы имплементируем три наиболее распространенных функции AJAX, которые могут быть сегодня найдены в веб-приложениях. Однако, прежде, мы узнаем о преимуществах использования инфраструктуры AJAX, в отличие от работы с raw JavaScript функциями.

    Использование AJAX фреймворка в Django

    Так как мы уже использовали bootstrap в нашем проекте, нам не нужно настраивать его отдельно для AJAX и jQuery.

    Есть много преимуществ использования AJAX фреймворка:

  • Имплементация JavaScript различается от браузера к браузеру. Некоторые браузеры обеспечивают более полную и богатую на функции имплементацию, тогда как другие содержат имплементации, которые являются неполными или не придерживающиеся стандартов.

    Без инфраструктуры AJAX разработчики должны отслеживать поддержку браузера для возможностей JavaScript, которые они используют и должны работать вокруг ограничений, которые присутствуют в некоторых браузерах для выполнения JavaScript.

    С другой стороны, при использовании фреймворка AJAX, фреймворк заботится об этом для нас; он абстрагирует доступ к имплементации JavaScript и сделок с шин различия и особенности JavaScript в браузерах. Банки металлические способом, мы можем сосредоточиться на разработке функции вместо тревожиться о браузере различия и ограничения.

  • Стандартного набора JavaScript функций и классов немного не хватает для полноценной разработки веб-приложений. Различные общие задачи требуют много строк кода, даже несмотря на то, что они могут быть обернуты в простые функции.

    Поэтому даже если вы не решитесь использовать инфраструктуру AJAX, вы найдете для себя написание библиотеки функций, которая инкапсулирует JavaScript зал и делает их более удобными. Однако, зачем изобретать велосипед, когда много отличных библиотек open source уже доступно?

  • AJAX фреймворки, имеющихся на рынке сегодня варьируются от всеобъемлющих решений, которые предоставляют серверные и клиентские компоненты до легких клиентских библиотек, которые упрощают работу с JavaScript. Учитывая, что мы уже используем Django на серверной стороне, мы хотим фреймворк только с клиентской стороны. В дополнение к этому фреймворк должны быть легко интегрируем с Django без требования любых дополнительных зависимостей. Наконец, желательно, выбрать легкий и быстрый фреймворк. Есть множество отличных фреймворков, которые отвечают нашим требованиям, таких как Prototype, Yahoo! UI Library, и jQuery.

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

    Вам нужно также импортировать bootstrap и jQuery.Таким образом, не нужно никакой особой установки или импорта для использования функций AJAX в нашем проекте Django.

    Использование open source фреймворка jQuery

    Прежде чем мы начнем имплементировать улучшения AJAX в наш проект, давайте пройдем через краткое введение в основы jQuery.

    JavaScript фреймворк JQuery

    jQuery — это библиотека функций JavaScript, которая облегчает взаимодействие с HTML-документами и управляет им. Библиотека предназначена для сокращения времени и усилий на написание кода и достижения совместимости между браузерами, и в то же время она в полной мере использует то, что JavaScript предлагает для создания гибких и интерактивных веб-приложений.

    Рабочий процесс с помощью jQuery в общем состоит из следующих двух этапов:

  • Выбор HTML-элемента или группу элементов для работы.
  • Применение метода jQuery к выбранной группе.
  • Селекторы элемента

    jQuery предоставляет простой подход для выбора элементов: она работает путем передачи строки селектора CSS в функцию $ (). Ниже приведены некоторые примеры, которые иллюстрируют использование этой функции :

  • Если вы хотите выбрать все привязки (<a>) элементов на странице, можно использовать вызов функции $ ("a").
  • Если вы хотите, выбрать элементы привязки, которые имеют CSS класс .title, используйте $("a.title")
  • Чтобы выбрать элемент, идентификатор которого является #nav, можно использовать $ ("#nav")
  • Для выбора всех элементов списка (<li>) внутри #nav, используйте $ ("#nav li")
  • Функция $ () создает и возвращает объект jQuery.После этого можно вызывать методы этого объекта для взаимодействия с выбранным HTML-элементом.

    Методы jQuery

    jQuery предлагает разнообразные методы для обработки HTML документов. Вы можете скрыть или показать элементы, присоединить обработчики событий к событиям, изменять свойства CSS, манипулировать структурой страницы и, самое главное, формировать AJAX-запросы.

    Для отладки, мы выберем браузер Internet Explorer как браузер нашего выбора. Internet Explorer является одним из самых передовых JavaScript отладчиком в виде его инструментов разработчика Django. Чтобы запустить его, нажмите на клавиатуре Ctrl + Shift + J.

    Поэкспериментируем с методами, изложенными в этом разделе, запустим сервер разработки и перейдем на страницу профиля пользователя (http: //127.0.0.1:8000/user/test/). Откройте консоль инструментов(нажав на клавиатуре Ctrl + Shift + J) разработчика и нажмите F12, попробуйте выбрать элементов и манипулировать ими.

    Скрытие и отображение элементов

    Давайте начнем с чего-то простого. Чтобы скрыть элемент на странице, вызовите метод — hide() на нем.Чтобы показать его снова, вызовите метод show(). Например попробуйте это с меню навигации, называемом navbar в загрузчик приложения:

    >>> $(".navbar").hide()
    >>> $(".navbar").show()
    

    Также можно анимировать элемент во время скрытия и показа его. Попробуйте fadeOut(), fadeln(), slideUp() или slideDown () — методы, чтобы увидеть два из этих анимационных эффекта.

    Конечно эти методы (как и все другие методы jQuery) также работают, если вы выберете более одного элемента за один раз. Например, если открыть профиль пользователя и ввести следующий вызов метода в консоли средства разработчика, все твиты исчезнут:

    >>> $(".well").slideUp()

    Доступ к свойствам CSS и HTML атрибутам

    Далее мы узнаем, как изменить свойства CSS элементов. jQuery предлагает метод, называемый css() для выполнения CSS операций. Если вызвать этот метод с именем свойства CSS, переданным в виде строки, она возвращает значение этого свойства:

    >>> $(".navbar").css("display")

    Результатом этого является следующее:

    block

    Если второй аргумент передается в этот метод, он задает указанное свойство CSS выбранного элемента для дополнительного аргумента:

    >>> $(".navbar").css("font-size", "0.8pt")

    Результатом этого является следующее сообщение:

    <div id="nav" style="font-size: 0.8em;"></div>

    В самом деле вы можете манипулировать любой атрибут м HTML и не только свойствами CSS. Чтобы сделать это, используйте метод attr(), который работает аналогично методу css(). Вызвав его по имени атрибута, он возвращает значение атрибута, в то время как его вызов с именем атрибута или пары значений задает атрибуту переданное значение:

    >>> $("input").attr ("size", "48")

    Это приводит к следующему:

    <input id="idcountry" name="country" type="hidden" value="Global" size="48">
    <input type="submit" value="post" size="48">
    

    Это одновременно изменит размер всех входных элементов на 48.

    В дополнение к этому, есть методы ярлыка, чтобы получать и устанавливать часто используемые атрибуты, такие как val(), который возвращает значение поля ввода, когда вызывается без аргументов и задает значение для аргумента, если вы передадите аргумент. Существует также метод html() для контроля HTML кода внутри элемента.

    Наконец, существует два метода, которые могут использоваться для присоединения или отсоединения CSS класса для элемента: это методы addClass() и removeClass(). Третий метод служит для переключения CSS класса и он называется методом toggleClass (). Все эти методы класса принимают имя класса, который необходимо изменить как параметр.

    Манипуляция HTML-документами

    Теперь, когда вам удобно манипулировать HTML-элементами, давайте посмотрим, как добавлять новые элементы или удалить существующие элементы. Чтобы вставить HTML-код перед элементом, используйте метод before(), а для вставки кода после элемента, используйте метод after().Обратите внимание, как методы jQuery хорошо именованы и их очень легко запомнить!

    Давайте протестируем эти методы, вставив скобки вокруг списков тегов на странице пользователя. Откройте вашу пользовательскую страницу и введите следующее в консоли средств разработчика:

    >>> $(".well span").before ("<strong>(</strong>")
    >>> $(".well span").after ("<strong>)</strong>")
    

    Вы можете передать любую строку, какую вы хотите, с методами before() или after(). Строка может содержать обычный текст, один или больше элементов HTML. Эти методы предоставляют очень гибкий способ для динамического добавления элементов HTML в документ HTML.

    Если вы хотите удалить элемент, используйте метод remove(). Например:

    $("#navbar").remove()

    Этот метод не только скрывает элемент, он также удаляет его полностью из дерева документов. Если вы попытаетесь выбрать элемент снова, после использования метода remove (), вы получите пустой набор:

    >>> $("#nav")

    Результатом этого является следующим:

    []

    Конечно, это только удаляет элементы из текущего экземпляра страницы. Если вы обновите страницу, элементы появятся снова.

    Обход дерева документов

    Хотя CSS селекторы предоставляют очень мощный способ для выбора элементов, бывают случаи, когда вы можете захотеть обойти дерево документа, начиная от конкретного элемента.

    Для этого jQuery предоставляет несколько методов. Метод parent () возвращает родителя текущего выбранного элемента. Метод children () возвращает всех непосредственных дочерних элементов выбранного элемента. Наконец, метод find () возвращает всех потомков текущего выбранного элемента. Все эти методы принимают необязательную строку CSS селектора для ограничения элементов теми, которые соответствуют результату селектора. Например, $(".column").find("span") возвращает всех потомков <span> столбца aclass.

    Если вы хотите получить доступ к отдельному элементу группы, используйте метод get (), который принимает индекс элемента в качестве параметра. Метод $("span").get(0), например, возвращает первый элемент <span> из выбранной группы.

    Обработка событий

    Далее мы изучим обработчики событий. Обработчик событий — это функция JavaScript, которая вызывается, когда происходит определенное событие, например, при нажатии кнопки или отправке формы. jQuery предоставляет большой набор методов для присоединения обработчиков к событиям; события, представляющие особый интерес в нашем приложении - щелчки мышью и отправка формы. Для обработки события нажатия на элемент, мы выбираем этот элемент и вызываем метод click(). Этот метод принимает в качестве параметра функцию обработчика событий. Давайте попробуем это в нашей консоли разработчика.

    Откройте страницу профиля пользователя приложения и вставьте кнопку после твита:

    >>> $(".well span").after("cbutton id=\"test-button\">Нажми!</ button>")

    Обратите внимание, что нам пришлось опустить кавычки в строках переданных методу after().

    Если вы попытаетесь нажать кнопку, ничего не произойдет, так что давайте присоединим обработчик событий к нему:

    >>> $("#test-button").click(function () { alert("Вы меня нажали!"); })

    Теперь, когда вы нажмете на кнопку,появится окно сообщения.Как это работает?

    Аргумент, который мы передали в методе click(), может выглядеть немного сложным, так что давайте рассмотрим его снова:

    function () { alert("Вы меня нажали!"); }

    Кажется, что это должно быть объявлением функции, но без имени функции. Действительно эта конструкция создает так называемую анонимную функцию в терминологии JavaScript, и она используется, когда вам нужно создать функцию на лету и передать ее в качестве аргумента другой функции. Мы могли бы избежать с помощью анонимных функций и объявить обработчик события как обычную функцию

    >>> function handler{ alertC("Вы нажали меня!"); }
    >>> $("#test-button").click(handler)
    

    Предыдущий код достигает того же эффекта, но первый является более кратким и компактным. Я настоятельно рекомендую вам привыкнуть к анонимным функциям в JavaScript (если вы еще не привыкли), как я уверен, что вы оцените эту конструкцию и найдете ее более удобной для чтения после использования его некоторое время.

    Обработка формы отправки очень похоже на обработку щелчков мыши. Сначала выберите форму, затем вызовите метод отправки на нее, и затем передайте обработчик в качестве аргумента. Мы будем использовать этот метод несколько раз во время добавления функций AJAX к нашему проекту в последующих разделах.

    Отправка запросов AJAX

    Прежде чем мы закончим этот раздел, давайте поговорим о AJAX-запросах. jQuery предоставляет много способов, чтобы отправлять запросы AJAX на сервер. Существует, например, метод load(), который принимает URL-адрес и загружает страницу по URL-адресу в выбранный элемент. Существуют также методы для отправки запросов GET или POST и получения результатов. Мы изучим эти методы более подробно при имплементации функций AJAX в наш проект.

    Реализация поиска твитов

    Мы будем постепенно вводить AJAX в наше приложение путем реализации живого поиска. Идея эта функции проста: когда пользователь вводит несколько ключевых слов в текстовое поле и нажимает на поиск, за кулисами срабатывает сценарий, чтобы получить результаты поиска и представить их на той же странице. Страница поиска не перезагружается, таким образом экономя пропускную способность и обеспечивая лучший и более отзывчивый опыт пользователя.

    Прежде чем мы постепенно это реализуем, нам нужно иметь в виду одно важное правило работы с AJAX: напишите приложение, так чтобы оно работало без AJAX и затем предоставьте к нему AJAX. Если вы сделаете это, вы убедитесь, что каждый будет иметь возможность использовать ваше приложение, включая пользователей, которые не имеют JavaScript, а также включая и тех, кто используют браузеры без поддержки AJAX.

    Так что прежде чем мы поработаем с AJAX давайте напишите простое представление, чтобы искать по названию закладки. Во-первых нам нужно создать форму поиска, поэтому откройте файл tweets/forms.py и добавьте в него следующий класс:

    Сlass SearchForm(forms.Form):
        query = forms.CharField(label='Enter a keyword to search for',
      widget=forms.TextInput(attrs={'size': 32, 'class':'form-control search-query'}))
    

    Как вы можете видеть, это довольно простой класс формы с только одним текстовым полем. Это поле будет использоваться пользователем для ввода ключевых слов поиска. Далее создадим представление для проведения поиска. Откройте файл tweets/views.py и введите следующий код в него:

    class Search(View):
        """Search all tweets with query /search/?query=<query> URL"""
        def get(self, request):
            form = SearchForm()
            params = dict()
            params["search"] = form
            return render(request, 'search.html', params)
    
        def post(self, request):
            form = SearchForm(request.POST)
            if form.is_valid():
                query = form.cleaned_data['query']
                tweets = Tweet.objects.filter(text__icontains=query)
                context = Context({"query": query, "tweets": tweets})
                return_str = render_to_string('partials/_tweet_search.html', context)
                return HttpResponse(json.dumps(return_str), content_type="application/json")
            else:
                HttpResponseRedirect("/search")
    

    Помимо нескольких вызовов метода представление должно быть очень легко для понимания.

    Если вы посмотрите на запрос GET, здесь все довольно просто, он подготавливает форму поиска и затем отображает ее.

    Метод post() является тем методом где происходит волшебство. Когда мы отображаем результаты поиска, это просто макета отображения с формой поиска, так что если вы взглянете на новый файл, который мы создали, под названием search.html, вы можете увидеть следующее:

    {% extends "base.html" %} 
    {% load staticfiles %}
    {% block content %}
    
    <div class="row clearfix">
            <div class="col-md-6 col-md-offset-3 column">
                <form id="search-form" action="" method="post">{% csrf_token %}
                <div class="input-group input-group-sm">
                        {{ search.query.errors }}
                        {{ search.query }}
                      <span class="input-group-btn">
                        <button class="btn btn-search" type="submit">search</button>
                      </span>
                </div><!-- /input-group -->
              </form>
            </div>
    		<div class="col-md-12 column tweets">
    		</div>
    	</div>
    {% endblock %}
    {% block js %}
        <script src="{% static 'js/search.js' %}"></script>
    {% endblock %}
    

    Если вы посмотрите внимательно, вы увидите, что мы включили новый раздел раздела с именем {% block js %}. Концепция, используемая здесь, является такой же, как и {% block content %}, то есть, то что объявляется здесь, будет передаваться в файл base.html. Взяв это на заметку, посмотрим на измененный файл base.html. Мы увидим следующее:

    {% load staticfiles %}
    <html>
      <head>
        <link href="{% static 'css/bootstrap.min.css' %}"
              rel="stylesheet" media="screen">
        {% block css %}
        {% endblock %}
      </head>
      <body>
    <nav class="navbar navbar-default" role="navigation">
     <a class="navbar-brand" href="#">MyTweets</a>
        {% block navbar %}
        {% endblock %}
    </nav>
      <div class="container">
        {% block content %}
        {% endblock %}
    </div>
    <nav class="navbar navbar-default navbar-fixed-bottom" role="navigation">
         <p class="navbar-text navbar-right">Footer </p>
    </nav>
    <script src="{% static 'js/jquery-2.1.1.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    <script src="{% static 'js/base.js' %}"></script>
        {% block js %}
        {% endblock %}
     </body>
    </html>
    

    Предыдущий код ясно показывает два новых блока содержимого, а именно:

    {% block css %}
    {% endblock %}
    {% block js %}
    {% endblock %}
    

    Они используются для включения типов соответствующих файлов и для отображения типы файлов с основы, так что поддержка проекта становится намного проще с помощью простого правила объявлять только один файл CSS и JavaScript на странице. Мы осуществим это позже в книге с концепцией, называемой assets pipeline.

    Теперь, возвращаясь к нашей функции поиска AJAX, вы увидите, что этот файл search.html, аналогичен файлу tweet.html.

    Для функции поиска мы создадим новый URL-адрес, который нам нужно добавить к файлу urls.py следующим образом:

    url(r'^search/$', Search.as_view())
    
    urls.py
    
    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    from tweet.views import Index, Profile, PostTweet, HashTagCloud, Search
    
    admin.autodiscover()
    
    urlpatterns = patterns('',
        url(r'^$', Index.as_view()),
        url(r'^user/(\w+)/$', Profile.as_view()),
        url(r'^admin/', include(admin.site.urls)),
        url(r'^user/(\w+)/post/$', PostTweet.as_view()),
        url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
        url(r'^search/$', Search.as_view()),
    )
    

    В файле search.html мы определили метод search.js; давайте создадим этот файл Javascript, чтобы действительно выполнялся запрос AJAX

    $('#search-form').submit(function(e){
        $.post('/search/', $(this).serialize(), function(data){
           $('.tweets').html(data);
        });
        e.preventDefault();
    });

    Этот код JavaScript срабатывает при отправке формы, это формирует AJAX запрос post к /search пользователя с сериализованной формы данных и он получает ответ. Затем, получив ответ, он добавляет данные к элементу класса твитов.

    Если мы откроем пользовательский поиск в браузере, он будет выглядеть как на следующем скриншоте:

    Но подождите! Что случится с этой формой при отправке? В AJAX-запрос отправляется метод post () класса search, который является следующим:

    def post(self, request):
            form = SearchForm(request.POST)
            if form.is_valid():
                query = form.cleaned_data['query']
                tweets = Tweet.objects.filter(text__icontains==query)
                context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
               return HttpResponse(json.dumps(return_str), content_type="application/json")
            else:
                HttpResponseRedirect("/search")
    

    Мы проверяем правильность формы после того, как мы извлекаем из запроса метод request.POST; Если форма является валидной, запрос извлекается из объекта Form.

    Затем, метод tweets = Tweet.objects.filter(text__icontains==query) ищет совпадение подстроки для данного термина запроса.

    Поиски проводятся с помощью метода под названием filter(text__icontains==query)в модуле Tweet.objects .Вы можете подумать о нем как об эквиваленте оператора SELECT в модели Django. Он получает критерии поиска в качестве своих аргументов и возвращает результат поиска.Имя каждого аргумента должно придерживаться следующего контекста именования:

    field__operator

    Обратите внимание, что переменные field и operator разделяются двумя нижними подчеркиваниями: поле, которое является именем поля, которое мы хотим искать, и оператор, который является методом поиска, который мы хотим использовать. Вот список часто используемых операторов:

  • exact : Это значение аргумента, который является точным соответствием поля
  • contains: Поле содержит значение аргумента
  • StartsWith: Это поле начинается со значения аргумента
  • lt: Это поле меньше, чем значение аргумента
  • gt: Это поле больше, чем значение аргумента
  • Кроме того, существуют версии нечувствительные к регистру первых трех операторов: iexact, icontains и istartswith, которые могут быть также включены в список.

    Единственное, что мы делаем совершенно по разному,следующее:

    context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
               return HttpResponse(json.dumps(return_str), content_type="application/json")
    

    Нашей целью было загрузить результаты поиска без перезагрузки или обновления на странице поиска. Если это так, тогда как наши предыдущий метод отображения поможет нам? Он не поможет. Нам нужны некоторые методы, которые могут помочь отправить данные браузеру без его перезагрузки.

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

    Чтобы реализовать этот метод, мы сначала создадим каталог под названием partials в существующей папке templates, файл _tweet_search.html со следующим содержимым:

    {% for tweet in tweets %}
        <div class="well">
            <span>{{ tweet.text }}</span>
        </div>
    {% endfor %}
    {% if not tweets %}
        <div class="well">
            <span> Не найдено твитов.</span>
        </div>
    {% endif %}
    

    Код будет отображать весь объект tweet в поле well или, если не найден объект tweet, он будет отображать внутри окна well Не найдено твитов.

    Вышеприведенная концепция отображает partials как строки в представлении, и если мы должны передать какие-либо параметры для отображения, мы должны передать их в первую очередь с вызовом для создания строки из partials. Чтобы передать параметры partials, нам нужно создать объект контекста и затем передать наши параметры:

    context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
    

    Таким образом, мы будем создавать контекст с запросом (который мы будем использовать позже) и параметры tweets и использовать функцию render_to_string (). Затем мы можем использовать JSON для дампа строки в функцию HttpResponse ():

    return HttpResponse(json.dumps(return_str), content_type="application/json")

    Список импорта являются следующим:

    from django.views.generic import View,TemplateView
    from django.shortcuts import render
    from user_profile.models import User, UserFollower
    from tweet.models import Tweet, HashTag
    from tweet.forms import TweetForm, SearchForm, SearchHashTagForm
    from django.http import HttpResponseRedirect
    from django.template.loader import render_to_string
    from django.template import Context
    from django.http import HttpResponse
    import json
    

    Вот оно что! Мы завершили базовый поиск на основе AJAX для поиска твитов.Поиск по слову django выдаст нам 3 твита, которые мы создали, так, как показано на следующем скриншоте:

    Идите вперед и поиграйте с поисковой системой, и я уверен, что вы будете еще больше влюбитесь в Django.

    Теперь у нас есть страница функционального (хотя и очень простого) поиска. В течение последующих глав будет улучшена функциональность поиска, сам, но сейчас для нас главное ввести AJAX в форму поиска, так чтобы результаты были получены за кулисами и представлены пользователю без перезагрузки страницы. Благодаря нашему модулярному коду, эта задача окажется намного проще, чем это может показаться.

    Автодополнение хэштегов при отправке твита

    Автозавершение тегов является последним расширением AJAX, которое мы осуществим в этой главе. Концепция автозавершения нашла свой путь среди веб-приложений, когда Google выпустила свой интерфейс предугадывания поисковых запросов. Предугадывание показывает самые популярные поисковые запросы, ниже поле ввода поиска, основанные на том, что пользователь вводит. Это также похоже на то, как редакторы кода в интегрированных средах разработки автоматически завершают код, основываясь на том, что вы вводите. Эта возможность экономит время, позволяя пользователю напечатать несколько символов слова, которое они хотят напечатать и затем позволяет им выбрать его из списка без необходимости вводить его в полностью.

    Мы имплементируем эту функцию предлагая преположительные варианты, когда пользователь вводит теги при отправке, но вместо того чтобы писать эту особенность с нуля, мы собираемся использовать плагин jQuery для его реализации .jQuery располагает большим и постоянно растущим списком плагинов, которые предоставляют разнообразные возможности Установка плагина является ничем не отличается от установки самого jQueiy. Вы скачиваете один (или более) файлов и привязываете их к вашему шаблону и вы должны написать несколько строк кода JavaScript, чтобы активировать плагин.

    Вы можете просматривать список доступных jQuery плагинов, перейдя на http://docs.jquery.com/plugins. Найдите в списке плагин автозаполнения и скачайте его, или вы можете взять его непосредственно на http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/.

    Вы получите zip-архив с большим количеством файлов в нем. Извлеките файлы (которые можно найти в каталоге jquery/autocomplete/scroll) в каталог static/js:

  • jQuery. autocomplete.css
  • Dimensions.js
  • jQuery. bgiframe.min.js
  • jQuery.autocomplete.js
  • Поскольку мы хотим предложить функцию автозаполнения на странице представления закладки, создайте пустой файл под названием tag_autocomplete.js в папке js. Затем откройте файл template/bookmark_save.html и и свяжите все предыдущие файлы в нем:

    {% extends "base.html" %}
    {% block external %}
    <link rel="stylesheet"
    href="/site_media/jquery.autocomplete.css" type="text/css" />
    <script type="text/javascript"
    src="/site_media/dimensions.js"> </script>
    <script type="text/javascript"
    src="/site_media/j query.bgiframe.min.j s"> </script>
    <script type="text/javascript"
    src="/site_media/j query.autocomplete.j s"> </script>
    <script type="text/javascript"
    src="/site_media/tag_autocomplete.js"> </script>
    {% endblock %}
    {% block title %}Save Bookmark{% endblock %}
    {% block head %}Save Bookmark{% endblock %}
    [. . .1
    

    Теперь мы закончили установку плагина, и, если вы прочитаете документацию о нем, вы обнаружите что что этот плагин активирован путем вызова метода с именем autocomplete () на выбранный элемент ввода. Функция autocomplete () принимает следующие параметры:

  • URL-адрес со стороны сервера: для этого, плагин отправляет GET запрос по URL-адресу с тем, что было введено и ожидает от сервера возврата набора предложений.
  • Объект, который может использоваться для указания различных параметров: Параметров, которые представляют интерес для нас множество. Этот параметр имеет логическое значение переменной, которое сообщает плагину, что поле ввода используется для ввода нескольких значений (Помните, что мы используем же текстовое поле для ввода всех тегов) и множества разделителей , которые обычно говорят плагину, какая строка отделяет несколько записей. В нашем случае это один пробел.
  • Перед активацией плагина, нам нужно написать представление, которое получает входные данные пользователя и возвращает набор предложений .Откройте файл tweets/view.py и добавьте следующее в конце:

    def AJAX_tag_autocomplete(request): 
    if request.GET.has_key(‘q’):):): 
    tags = \
    Tag.objects.filter(name istartswith=request.GET [‘q’]) [:10]
    return HttpResponse('\n'.join(tag.name for tag in tags)) 
    return HttpResponse()
    

    Плагин autocomplete() отправляет пользовательский ввод в GET-переменную с именем q. Таким образом, мы можем убедиться, что эта переменная существует и построить список тегов, имена которых начинаются со значения этой переменной. Это сделано с помощью метода filter() и оператора istartswith, о котором мы узнали ранее в главе. Мы выберем только первые десять результатов чтобы избежать ошеломления пользователя предложениями и снизить расходы на пропускную способность и производительность. Наконец мы соединяем предложения в одну строку, разделенные знаками новой строки, переносим строки в объект HttpResponse и возвращаем его.

    Так как представление готово, добавим запись о плагине в файл, как показано ниже:

    urlpattems = patterns ('
    # AJAX
    (r'^AJAX/tag/autocomplete/$', AJAX_tag_autocomplete),
    )
    

    Теперь Активируйте плагин на поле ввода тегов, введя следующий код в файл js/tag_autocomplete.js:

    $(document).ready(function () {
    $("#id_tags").autocomplete(
    '/AJAX/tag/autocomplete/',
    {multiple: true, multipleSeparator:	1	'}
    ) ;
    }>;
    

    Код передает анонимную функцию методу $(document).ready (). Эта функция вызывает функцию autocomplete() на поле ввода тегов, передает аргументы, о которых мы говорили ранее.

    Эти несколько строк кода - все, что нам нужно для того, чтобы имплементировать автоматическое заполнение тегов. Чтобы проверить новую функцию, перейдите к http: //127.0.0.l: 8000/save/ и попробуйте ввести символ или два в поле тегов. Предложения должны появиться основе тегов доступных в вашей базе данных.

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

    Следующая лекция будет рассказывать о другой теме: мы позволим пользователям голосовать и комментировать свои любимые закладки и на первой странице нашего приложения не останется так пусто, как сейчас!

    Контрольные вопросы

  • Для чего нужен живой поиск для поиска твитов?
  • Что такое технология AJAX?
  • Перечислите приемущества технологии AJAX
  • Что такое обработчик событий?
  • Что такое jQuery?
  • Упражнения

    Упражнение 1.

    Добавьте живой поиск по твитам

    Упражнение 2.

    Измените код таким образом, чтобы результаты поиска отображались на отдельной странице

    Упражнение 3.

    Добавьте возможность поиска твитов с учетов даты

    Упражнение 4.

    Добавьте возможность регистрации пользователей

    Список тем курсовых работ

  • Прототипирование приложения для ведения блогов
  • Создание прототипа приложения для сокращения ссылок
  • Создание прототипа приложения для твитов с использованием альтернативного js-фреймворка
  • Технология AJAX как современная веб-технология
  • Создание прототипа проекта форума
  • Разработка веб-почтового клиента(прототип)
  • Создание прототипа приложения для хранения заметок
  • Создание прототипа социальной сети
  • Доработка приложения для твитов путем добавления возможности общения по электронной почте
  • Прототипирование сервиса для хранения ссылок пользователей
  • Краткие итоги

  • Создали страницу поиска твита
  • Узнали об основных возможностях AJAX
  • Дополнили приложение функцией автодополнения хэштегов
  • Узнали о методах JQuery
  • Узнали об особенностях фреймворка JQuery
  • Научились обрабатыват ьсобытия
  • Узнали о способе доступа к CSS и HTML атрибутам
  • Создали класс для поиска твитов
  • Создали js-скрипты
  • Добавили в HTML-страницы возможность выполнения js-скриптов
  • Страницы:

    Цель лекции: рассмотреть основы технологии AJAX, познакомиться с понятием формы, рассмотреть основные типы виджетов, создать страницу поиска твитов, познакомиться с методами jQuery, добавить автодополнение хэштегов при отправке твита.

    Ключевые термины: AJAX, CSS, HTML, jQuery, форма, фреймворк, твит, хештег, имплементация, элемент, запрос, поиск, метод, атрибут, приложение.

    Появление AJAX стало важной вехой в истории Веб 2.0. AJAX — это группа технологий, что позволяет разработчикам создавать интерактивные, с большими возможностями веб-приложения. Большинство из этих технологий были доступны за многие годы до появления самого AJAX. Однако появление AJAX представляет переход Web от статических страниц, которые необходимо обновлять всякий раз, когда происходил обмен данными к динамическим, гибким и интерактивным пользовательским интерфейсам.

    Так как наш проект является приложением Веб 2.0, оно должно быть более нацелено на пользователей. Успех нашего приложения зависит от получения пользователем возможности размещать и обмениваться контентом на нем. Таким образом, пользовательский интерфейс нашего приложения является одной из наших основных проблем. Эта лекция улучшит интерфейс нашего приложения с помощью описания возможностей AJAX, что сделает его более удобным для пользователей и интерактивным.

    AJAX и его преимущества

    AJAX, которая расшифовывается как Asynchronous JavaScript and XML (Асинхронный JavaScript и XML), состоит из следующих технологий:

  • HTML и CSS для структурирования информации и придания стилей
  • JavaScript для динамического доступа и манипулирования информацией
  • Объект XMLHttpRequest, который представляет собой объект, предоставляемый современнми браузерами для обмена данными с сервером без перезагрузки текущей веб-страницы
  • Формат для передачи данных между клиентом и сервером
  • Иногда используется XML, но это может быть в HTML, обычном тексте или формате на основе JavaScript, называемом JSON.

    AJAX технологии позволяют кодировать обмен данными на клиентской стороне с сервером за кулисами, без перезагрузки всей страницы каждый раз, когда пользователь делает запрос. С помощью AJAX, веб-разработчик может увеличить интерактивность и удобство использования ' веб-страниц.

    AJAX обеспечивает следующие преимущества при имплементации в правильных местах:

  • Улучшение опыта пользователя: пользователь с AJAX может сделать много без обновления страницы, которая делает веб-приложения ближе к обычным настольным приложениям
  • Лучшая производительность: путем обмена только требуемых данных внутри сервера, AJAX сохраняет пропускную способность и увеличивает скорость приложений
  • Существует множество примеров веб-приложений, использующих AJAX: карты Google и Gmail, возможно, два наиболее известных примера. В самом деле, эти два приложения играют важную роль в распространении использования AJAX из-за того успеха, которыми они пользуются. Что отличает Gmail от других почтовых сервисов, это его пользовательский интерфейс, который позволяет пользователям интерактивно управлять электронной почтой, не дожидаясь перезагрузки страницы после каждого действия, и это создает лучший пользовательский опыт и позволяет Gmail чувствовать себя отзывчивым и многофункциональным приложением, нежели простой веб-сайт.

    В этой лекции объясняется, как использовать AJAX с Django, с тем чтобы сделать приложения более гибким и удобным для пользователей. Мы имплементируем три наиболее распространенных функции AJAX, которые могут быть сегодня найдены в веб-приложениях. Однако, прежде, мы узнаем о преимуществах использования инфраструктуры AJAX, в отличие от работы с raw JavaScript функциями.

    Использование AJAX фреймворка в Django

    Так как мы уже использовали bootstrap в нашем проекте, нам не нужно настраивать его отдельно для AJAX и jQuery.

    Есть много преимуществ использования AJAX фреймворка:

  • Имплементация JavaScript различается от браузера к браузеру. Некоторые браузеры обеспечивают более полную и богатую на функции имплементацию, тогда как другие содержат имплементации, которые являются неполными или не придерживающиеся стандартов.

    Без инфраструктуры AJAX разработчики должны отслеживать поддержку браузера для возможностей JavaScript, которые они используют и должны работать вокруг ограничений, которые присутствуют в некоторых браузерах для выполнения JavaScript.

    С другой стороны, при использовании фреймворка AJAX, фреймворк заботится об этом для нас; он абстрагирует доступ к имплементации JavaScript и сделок с шин различия и особенности JavaScript в браузерах. Банки металлические способом, мы можем сосредоточиться на разработке функции вместо тревожиться о браузере различия и ограничения.

  • Стандартного набора JavaScript функций и классов немного не хватает для полноценной разработки веб-приложений. Различные общие задачи требуют много строк кода, даже несмотря на то, что они могут быть обернуты в простые функции.

    Поэтому даже если вы не решитесь использовать инфраструктуру AJAX, вы найдете для себя написание библиотеки функций, которая инкапсулирует JavaScript зал и делает их более удобными. Однако, зачем изобретать велосипед, когда много отличных библиотек open source уже доступно?

  • AJAX фреймворки, имеющихся на рынке сегодня варьируются от всеобъемлющих решений, которые предоставляют серверные и клиентские компоненты до легких клиентских библиотек, которые упрощают работу с JavaScript. Учитывая, что мы уже используем Django на серверной стороне, мы хотим фреймворк только с клиентской стороны. В дополнение к этому фреймворк должны быть легко интегрируем с Django без требования любых дополнительных зависимостей. Наконец, желательно, выбрать легкий и быстрый фреймворк. Есть множество отличных фреймворков, которые отвечают нашим требованиям, таких как Prototype, Yahoo! UI Library, и jQuery.

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

    Вам нужно также импортировать bootstrap и jQuery.Таким образом, не нужно никакой особой установки или импорта для использования функций AJAX в нашем проекте Django.

    Использование open source фреймворка jQuery

    Прежде чем мы начнем имплементировать улучшения AJAX в наш проект, давайте пройдем через краткое введение в основы jQuery.

    JavaScript фреймворк JQuery

    jQuery — это библиотека функций JavaScript, которая облегчает взаимодействие с HTML-документами и управляет им. Библиотека предназначена для сокращения времени и усилий на написание кода и достижения совместимости между браузерами, и в то же время она в полной мере использует то, что JavaScript предлагает для создания гибких и интерактивных веб-приложений.

    Рабочий процесс с помощью jQuery в общем состоит из следующих двух этапов:

  • Выбор HTML-элемента или группу элементов для работы.
  • Применение метода jQuery к выбранной группе.
  • Селекторы элемента

    jQuery предоставляет простой подход для выбора элементов: она работает путем передачи строки селектора CSS в функцию $ (). Ниже приведены некоторые примеры, которые иллюстрируют использование этой функции :

  • Если вы хотите выбрать все привязки (<a>) элементов на странице, можно использовать вызов функции $ ("a").
  • Если вы хотите, выбрать элементы привязки, которые имеют CSS класс .title, используйте $("a.title")
  • Чтобы выбрать элемент, идентификатор которого является #nav, можно использовать $ ("#nav")
  • Для выбора всех элементов списка (<li>) внутри #nav, используйте $ ("#nav li")
  • Функция $ () создает и возвращает объект jQuery.После этого можно вызывать методы этого объекта для взаимодействия с выбранным HTML-элементом.

    Методы jQuery

    jQuery предлагает разнообразные методы для обработки HTML документов. Вы можете скрыть или показать элементы, присоединить обработчики событий к событиям, изменять свойства CSS, манипулировать структурой страницы и, самое главное, формировать AJAX-запросы.

    Для отладки, мы выберем браузер Internet Explorer как браузер нашего выбора. Internet Explorer является одним из самых передовых JavaScript отладчиком в виде его инструментов разработчика Django. Чтобы запустить его, нажмите на клавиатуре Ctrl + Shift + J.

    Поэкспериментируем с методами, изложенными в этом разделе, запустим сервер разработки и перейдем на страницу профиля пользователя (http: //127.0.0.1:8000/user/test/). Откройте консоль инструментов(нажав на клавиатуре Ctrl + Shift + J) разработчика и нажмите F12, попробуйте выбрать элементов и манипулировать ими.

    Скрытие и отображение элементов

    Давайте начнем с чего-то простого. Чтобы скрыть элемент на странице, вызовите метод — hide() на нем.Чтобы показать его снова, вызовите метод show(). Например попробуйте это с меню навигации, называемом navbar в загрузчик приложения:

    >>> $(".navbar").hide()
    >>> $(".navbar").show()
    

    Также можно анимировать элемент во время скрытия и показа его. Попробуйте fadeOut(), fadeln(), slideUp() или slideDown () — методы, чтобы увидеть два из этих анимационных эффекта.

    Конечно эти методы (как и все другие методы jQuery) также работают, если вы выберете более одного элемента за один раз. Например, если открыть профиль пользователя и ввести следующий вызов метода в консоли средства разработчика, все твиты исчезнут:

    >>> $(".well").slideUp()

    Доступ к свойствам CSS и HTML атрибутам

    Далее мы узнаем, как изменить свойства CSS элементов. jQuery предлагает метод, называемый css() для выполнения CSS операций. Если вызвать этот метод с именем свойства CSS, переданным в виде строки, она возвращает значение этого свойства:

    >>> $(".navbar").css("display")

    Результатом этого является следующее:

    block

    Если второй аргумент передается в этот метод, он задает указанное свойство CSS выбранного элемента для дополнительного аргумента:

    >>> $(".navbar").css("font-size", "0.8pt")

    Результатом этого является следующее сообщение:

    <div id="nav" style="font-size: 0.8em;"></div>

    В самом деле вы можете манипулировать любой атрибут м HTML и не только свойствами CSS. Чтобы сделать это, используйте метод attr(), который работает аналогично методу css(). Вызвав его по имени атрибута, он возвращает значение атрибута, в то время как его вызов с именем атрибута или пары значений задает атрибуту переданное значение:

    >>> $("input").attr ("size", "48")

    Это приводит к следующему:

    <input id="idcountry" name="country" type="hidden" value="Global" size="48">
    <input type="submit" value="post" size="48">
    

    Это одновременно изменит размер всех входных элементов на 48.

    В дополнение к этому, есть методы ярлыка, чтобы получать и устанавливать часто используемые атрибуты, такие как val(), который возвращает значение поля ввода, когда вызывается без аргументов и задает значение для аргумента, если вы передадите аргумент. Существует также метод html() для контроля HTML кода внутри элемента.

    Наконец, существует два метода, которые могут использоваться для присоединения или отсоединения CSS класса для элемента: это методы addClass() и removeClass(). Третий метод служит для переключения CSS класса и он называется методом toggleClass (). Все эти методы класса принимают имя класса, который необходимо изменить как параметр.

    Манипуляция HTML-документами

    Теперь, когда вам удобно манипулировать HTML-элементами, давайте посмотрим, как добавлять новые элементы или удалить существующие элементы. Чтобы вставить HTML-код перед элементом, используйте метод before(), а для вставки кода после элемента, используйте метод after().Обратите внимание, как методы jQuery хорошо именованы и их очень легко запомнить!

    Давайте протестируем эти методы, вставив скобки вокруг списков тегов на странице пользователя. Откройте вашу пользовательскую страницу и введите следующее в консоли средств разработчика:

    >>> $(".well span").before ("<strong>(</strong>")
    >>> $(".well span").after ("<strong>)</strong>")
    

    Вы можете передать любую строку, какую вы хотите, с методами before() или after(). Строка может содержать обычный текст, один или больше элементов HTML. Эти методы предоставляют очень гибкий способ для динамического добавления элементов HTML в документ HTML.

    Если вы хотите удалить элемент, используйте метод remove(). Например:

    $("#navbar").remove()

    Этот метод не только скрывает элемент, он также удаляет его полностью из дерева документов. Если вы попытаетесь выбрать элемент снова, после использования метода remove (), вы получите пустой набор:

    >>> $("#nav")

    Результатом этого является следующим:

    []

    Конечно, это только удаляет элементы из текущего экземпляра страницы. Если вы обновите страницу, элементы появятся снова.

    Обход дерева документов

    Хотя CSS селекторы предоставляют очень мощный способ для выбора элементов, бывают случаи, когда вы можете захотеть обойти дерево документа, начиная от конкретного элемента.

    Для этого jQuery предоставляет несколько методов. Метод parent () возвращает родителя текущего выбранного элемента. Метод children () возвращает всех непосредственных дочерних элементов выбранного элемента. Наконец, метод find () возвращает всех потомков текущего выбранного элемента. Все эти методы принимают необязательную строку CSS селектора для ограничения элементов теми, которые соответствуют результату селектора. Например, $(".column").find("span") возвращает всех потомков <span> столбца aclass.

    Если вы хотите получить доступ к отдельному элементу группы, используйте метод get (), который принимает индекс элемента в качестве параметра. Метод $("span").get(0), например, возвращает первый элемент <span> из выбранной группы.

    Обработка событий

    Далее мы изучим обработчики событий. Обработчик событий — это функция JavaScript, которая вызывается, когда происходит определенное событие, например, при нажатии кнопки или отправке формы. jQuery предоставляет большой набор методов для присоединения обработчиков к событиям; события, представляющие особый интерес в нашем приложении - щелчки мышью и отправка формы. Для обработки события нажатия на элемент, мы выбираем этот элемент и вызываем метод click(). Этот метод принимает в качестве параметра функцию обработчика событий. Давайте попробуем это в нашей консоли разработчика.

    Откройте страницу профиля пользователя приложения и вставьте кнопку после твита:

    >>> $(".well span").after("cbutton id=\"test-button\">Нажми!</ button>")

    Обратите внимание, что нам пришлось опустить кавычки в строках переданных методу after().

    Если вы попытаетесь нажать кнопку, ничего не произойдет, так что давайте присоединим обработчик событий к нему:

    >>> $("#test-button").click(function () { alert("Вы меня нажали!"); })

    Теперь, когда вы нажмете на кнопку,появится окно сообщения.Как это работает?

    Аргумент, который мы передали в методе click(), может выглядеть немного сложным, так что давайте рассмотрим его снова:

    function () { alert("Вы меня нажали!"); }

    Кажется, что это должно быть объявлением функции, но без имени функции. Действительно эта конструкция создает так называемую анонимную функцию в терминологии JavaScript, и она используется, когда вам нужно создать функцию на лету и передать ее в качестве аргумента другой функции. Мы могли бы избежать с помощью анонимных функций и объявить обработчик события как обычную функцию

    >>> function handler{ alertC("Вы нажали меня!"); }
    >>> $("#test-button").click(handler)
    

    Предыдущий код достигает того же эффекта, но первый является более кратким и компактным. Я настоятельно рекомендую вам привыкнуть к анонимным функциям в JavaScript (если вы еще не привыкли), как я уверен, что вы оцените эту конструкцию и найдете ее более удобной для чтения после использования его некоторое время.

    Обработка формы отправки очень похоже на обработку щелчков мыши. Сначала выберите форму, затем вызовите метод отправки на нее, и затем передайте обработчик в качестве аргумента. Мы будем использовать этот метод несколько раз во время добавления функций AJAX к нашему проекту в последующих разделах.

    Отправка запросов AJAX

    Прежде чем мы закончим этот раздел, давайте поговорим о AJAX-запросах. jQuery предоставляет много способов, чтобы отправлять запросы AJAX на сервер. Существует, например, метод load(), который принимает URL-адрес и загружает страницу по URL-адресу в выбранный элемент. Существуют также методы для отправки запросов GET или POST и получения результатов. Мы изучим эти методы более подробно при имплементации функций AJAX в наш проект.

    Реализация поиска твитов

    Мы будем постепенно вводить AJAX в наше приложение путем реализации живого поиска. Идея эта функции проста: когда пользователь вводит несколько ключевых слов в текстовое поле и нажимает на поиск, за кулисами срабатывает сценарий, чтобы получить результаты поиска и представить их на той же странице. Страница поиска не перезагружается, таким образом экономя пропускную способность и обеспечивая лучший и более отзывчивый опыт пользователя.

    Прежде чем мы постепенно это реализуем, нам нужно иметь в виду одно важное правило работы с AJAX: напишите приложение, так чтобы оно работало без AJAX и затем предоставьте к нему AJAX. Если вы сделаете это, вы убедитесь, что каждый будет иметь возможность использовать ваше приложение, включая пользователей, которые не имеют JavaScript, а также включая и тех, кто используют браузеры без поддержки AJAX.

    Так что прежде чем мы поработаем с AJAX давайте напишите простое представление, чтобы искать по названию закладки. Во-первых нам нужно создать форму поиска, поэтому откройте файл tweets/forms.py и добавьте в него следующий класс:

    Сlass SearchForm(forms.Form):
        query = forms.CharField(label='Enter a keyword to search for',
      widget=forms.TextInput(attrs={'size': 32, 'class':'form-control search-query'}))
    

    Как вы можете видеть, это довольно простой класс формы с только одним текстовым полем. Это поле будет использоваться пользователем для ввода ключевых слов поиска. Далее создадим представление для проведения поиска. Откройте файл tweets/views.py и введите следующий код в него:

    class Search(View):
        """Search all tweets with query /search/?query=<query> URL"""
        def get(self, request):
            form = SearchForm()
            params = dict()
            params["search"] = form
            return render(request, 'search.html', params)
    
        def post(self, request):
            form = SearchForm(request.POST)
            if form.is_valid():
                query = form.cleaned_data['query']
                tweets = Tweet.objects.filter(text__icontains=query)
                context = Context({"query": query, "tweets": tweets})
                return_str = render_to_string('partials/_tweet_search.html', context)
                return HttpResponse(json.dumps(return_str), content_type="application/json")
            else:
                HttpResponseRedirect("/search")
    

    Помимо нескольких вызовов метода представление должно быть очень легко для понимания.

    Если вы посмотрите на запрос GET, здесь все довольно просто, он подготавливает форму поиска и затем отображает ее.

    Метод post() является тем методом где происходит волшебство. Когда мы отображаем результаты поиска, это просто макета отображения с формой поиска, так что если вы взглянете на новый файл, который мы создали, под названием search.html, вы можете увидеть следующее:

    {% extends "base.html" %} 
    {% load staticfiles %}
    {% block content %}
    
    <div class="row clearfix">
            <div class="col-md-6 col-md-offset-3 column">
                <form id="search-form" action="" method="post">{% csrf_token %}
                <div class="input-group input-group-sm">
                        {{ search.query.errors }}
                        {{ search.query }}
                      <span class="input-group-btn">
                        <button class="btn btn-search" type="submit">search</button>
                      </span>
                </div><!-- /input-group -->
              </form>
            </div>
    		<div class="col-md-12 column tweets">
    		</div>
    	</div>
    {% endblock %}
    {% block js %}
        <script src="{% static 'js/search.js' %}"></script>
    {% endblock %}
    

    Если вы посмотрите внимательно, вы увидите, что мы включили новый раздел раздела с именем {% block js %}. Концепция, используемая здесь, является такой же, как и {% block content %}, то есть, то что объявляется здесь, будет передаваться в файл base.html. Взяв это на заметку, посмотрим на измененный файл base.html. Мы увидим следующее:

    {% load staticfiles %}
    <html>
      <head>
        <link href="{% static 'css/bootstrap.min.css' %}"
              rel="stylesheet" media="screen">
        {% block css %}
        {% endblock %}
      </head>
      <body>
    <nav class="navbar navbar-default" role="navigation">
     <a class="navbar-brand" href="#">MyTweets</a>
        {% block navbar %}
        {% endblock %}
    </nav>
      <div class="container">
        {% block content %}
        {% endblock %}
    </div>
    <nav class="navbar navbar-default navbar-fixed-bottom" role="navigation">
         <p class="navbar-text navbar-right">Footer </p>
    </nav>
    <script src="{% static 'js/jquery-2.1.1.min.js' %}"></script>
    <script src="{% static 'js/bootstrap.min.js' %}"></script>
    <script src="{% static 'js/base.js' %}"></script>
        {% block js %}
        {% endblock %}
     </body>
    </html>
    

    Предыдущий код ясно показывает два новых блока содержимого, а именно:

    {% block css %}
    {% endblock %}
    {% block js %}
    {% endblock %}
    

    Они используются для включения типов соответствующих файлов и для отображения типы файлов с основы, так что поддержка проекта становится намного проще с помощью простого правила объявлять только один файл CSS и JavaScript на странице. Мы осуществим это позже в книге с концепцией, называемой assets pipeline.

    Теперь, возвращаясь к нашей функции поиска AJAX, вы увидите, что этот файл search.html, аналогичен файлу tweet.html.

    Для функции поиска мы создадим новый URL-адрес, который нам нужно добавить к файлу urls.py следующим образом:

    url(r'^search/$', Search.as_view())
    
    urls.py
    
    from django.conf.urls import patterns, include, url
    from django.contrib import admin
    from tweet.views import Index, Profile, PostTweet, HashTagCloud, Search
    
    admin.autodiscover()
    
    urlpatterns = patterns('',
        url(r'^$', Index.as_view()),
        url(r'^user/(\w+)/$', Profile.as_view()),
        url(r'^admin/', include(admin.site.urls)),
        url(r'^user/(\w+)/post/$', PostTweet.as_view()),
        url(r'^hashTag/(\w+)/$', HashTagCloud.as_view()),
        url(r'^search/$', Search.as_view()),
    )
    

    В файле search.html мы определили метод search.js; давайте создадим этот файл Javascript, чтобы действительно выполнялся запрос AJAX

    $('#search-form').submit(function(e){
        $.post('/search/', $(this).serialize(), function(data){
           $('.tweets').html(data);
        });
        e.preventDefault();
    });

    Этот код JavaScript срабатывает при отправке формы, это формирует AJAX запрос post к /search пользователя с сериализованной формы данных и он получает ответ. Затем, получив ответ, он добавляет данные к элементу класса твитов.

    Если мы откроем пользовательский поиск в браузере, он будет выглядеть как на следующем скриншоте:

    Но подождите! Что случится с этой формой при отправке? В AJAX-запрос отправляется метод post () класса search, который является следующим:

    def post(self, request):
            form = SearchForm(request.POST)
            if form.is_valid():
                query = form.cleaned_data['query']
                tweets = Tweet.objects.filter(text__icontains==query)
                context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
               return HttpResponse(json.dumps(return_str), content_type="application/json")
            else:
                HttpResponseRedirect("/search")
    

    Мы проверяем правильность формы после того, как мы извлекаем из запроса метод request.POST; Если форма является валидной, запрос извлекается из объекта Form.

    Затем, метод tweets = Tweet.objects.filter(text__icontains==query) ищет совпадение подстроки для данного термина запроса.

    Поиски проводятся с помощью метода под названием filter(text__icontains==query)в модуле Tweet.objects .Вы можете подумать о нем как об эквиваленте оператора SELECT в модели Django. Он получает критерии поиска в качестве своих аргументов и возвращает результат поиска.Имя каждого аргумента должно придерживаться следующего контекста именования:

    field__operator

    Обратите внимание, что переменные field и operator разделяются двумя нижними подчеркиваниями: поле, которое является именем поля, которое мы хотим искать, и оператор, который является методом поиска, который мы хотим использовать. Вот список часто используемых операторов:

  • exact : Это значение аргумента, который является точным соответствием поля
  • contains: Поле содержит значение аргумента
  • StartsWith: Это поле начинается со значения аргумента
  • lt: Это поле меньше, чем значение аргумента
  • gt: Это поле больше, чем значение аргумента
  • Кроме того, существуют версии нечувствительные к регистру первых трех операторов: iexact, icontains и istartswith, которые могут быть также включены в список.

    Единственное, что мы делаем совершенно по разному,следующее:

    context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
               return HttpResponse(json.dumps(return_str), content_type="application/json")
    

    Нашей целью было загрузить результаты поиска без перезагрузки или обновления на странице поиска. Если это так, тогда как наши предыдущий метод отображения поможет нам? Он не поможет. Нам нужны некоторые методы, которые могут помочь отправить данные браузеру без его перезагрузки.

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

    Чтобы реализовать этот метод, мы сначала создадим каталог под названием partials в существующей папке templates, файл _tweet_search.html со следующим содержимым:

    {% for tweet in tweets %}
        <div class="well">
            <span>{{ tweet.text }}</span>
        </div>
    {% endfor %}
    {% if not tweets %}
        <div class="well">
            <span> Не найдено твитов.</span>
        </div>
    {% endif %}
    

    Код будет отображать весь объект tweet в поле well или, если не найден объект tweet, он будет отображать внутри окна well Не найдено твитов.

    Вышеприведенная концепция отображает partials как строки в представлении, и если мы должны передать какие-либо параметры для отображения, мы должны передать их в первую очередь с вызовом для создания строки из partials. Чтобы передать параметры partials, нам нужно создать объект контекста и затем передать наши параметры:

    context = Context({"query": query, "tweets": tweets})
    
                return_str = render_to_string('partials/_tweet_search.html', context)
    

    Таким образом, мы будем создавать контекст с запросом (который мы будем использовать позже) и параметры tweets и использовать функцию render_to_string (). Затем мы можем использовать JSON для дампа строки в функцию HttpResponse ():

    return HttpResponse(json.dumps(return_str), content_type="application/json")

    Список импорта являются следующим:

    from django.views.generic import View,TemplateView
    from django.shortcuts import render
    from user_profile.models import User, UserFollower
    from tweet.models import Tweet, HashTag
    from tweet.forms import TweetForm, SearchForm, SearchHashTagForm
    from django.http import HttpResponseRedirect
    from django.template.loader import render_to_string
    from django.template import Context
    from django.http import HttpResponse
    import json
    

    Вот оно что! Мы завершили базовый поиск на основе AJAX для поиска твитов.Поиск по слову django выдаст нам 3 твита, которые мы создали, так, как показано на следующем скриншоте:

    Идите вперед и поиграйте с поисковой системой, и я уверен, что вы будете еще больше влюбитесь в Django.

    Теперь у нас есть страница функционального (хотя и очень простого) поиска. В течение последующих глав будет улучшена функциональность поиска, сам, но сейчас для нас главное ввести AJAX в форму поиска, так чтобы результаты были получены за кулисами и представлены пользователю без перезагрузки страницы. Благодаря нашему модулярному коду, эта задача окажется намного проще, чем это может показаться.

    Автодополнение хэштегов при отправке твита

    Автозавершение тегов является последним расширением AJAX, которое мы осуществим в этой главе. Концепция автозавершения нашла свой путь среди веб-приложений, когда Google выпустила свой интерфейс предугадывания поисковых запросов. Предугадывание показывает самые популярные поисковые запросы, ниже поле ввода поиска, основанные на том, что пользователь вводит. Это также похоже на то, как редакторы кода в интегрированных средах разработки автоматически завершают код, основываясь на том, что вы вводите. Эта возможность экономит время, позволяя пользователю напечатать несколько символов слова, которое они хотят напечатать и затем позволяет им выбрать его из списка без необходимости вводить его в полностью.

    Мы имплементируем эту функцию предлагая преположительные варианты, когда пользователь вводит теги при отправке, но вместо того чтобы писать эту особенность с нуля, мы собираемся использовать плагин jQuery для его реализации .jQuery располагает большим и постоянно растущим списком плагинов, которые предоставляют разнообразные возможности Установка плагина является ничем не отличается от установки самого jQueiy. Вы скачиваете один (или более) файлов и привязываете их к вашему шаблону и вы должны написать несколько строк кода JavaScript, чтобы активировать плагин.

    Вы можете просматривать список доступных jQuery плагинов, перейдя на http://docs.jquery.com/plugins. Найдите в списке плагин автозаполнения и скачайте его, или вы можете взять его непосредственно на http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/.

    Вы получите zip-архив с большим количеством файлов в нем. Извлеките файлы (которые можно найти в каталоге jquery/autocomplete/scroll) в каталог static/js:

  • jQuery. autocomplete.css
  • Dimensions.js
  • jQuery. bgiframe.min.js
  • jQuery.autocomplete.js
  • Поскольку мы хотим предложить функцию автозаполнения на странице представления закладки, создайте пустой файл под названием tag_autocomplete.js в папке js. Затем откройте файл template/bookmark_save.html и и свяжите все предыдущие файлы в нем:

    {% extends "base.html" %}
    {% block external %}
    <link rel="stylesheet"
    href="/site_media/jquery.autocomplete.css" type="text/css" />
    <script type="text/javascript"
    src="/site_media/dimensions.js"> </script>
    <script type="text/javascript"
    src="/site_media/j query.bgiframe.min.j s"> </script>
    <script type="text/javascript"
    src="/site_media/j query.autocomplete.j s"> </script>
    <script type="text/javascript"
    src="/site_media/tag_autocomplete.js"> </script>
    {% endblock %}
    {% block title %}Save Bookmark{% endblock %}
    {% block head %}Save Bookmark{% endblock %}
    [. . .1
    

    Теперь мы закончили установку плагина, и, если вы прочитаете документацию о нем, вы обнаружите что что этот плагин активирован путем вызова метода с именем autocomplete () на выбранный элемент ввода. Функция autocomplete () принимает следующие параметры:

  • URL-адрес со стороны сервера: для этого, плагин отправляет GET запрос по URL-адресу с тем, что было введено и ожидает от сервера возврата набора предложений.
  • Объект, который может использоваться для указания различных параметров: Параметров, которые представляют интерес для нас множество. Этот параметр имеет логическое значение переменной, которое сообщает плагину, что поле ввода используется для ввода нескольких значений (Помните, что мы используем же текстовое поле для ввода всех тегов) и множества разделителей , которые обычно говорят плагину, какая строка отделяет несколько записей. В нашем случае это один пробел.
  • Перед активацией плагина, нам нужно написать представление, которое получает входные данные пользователя и возвращает набор предложений .Откройте файл tweets/view.py и добавьте следующее в конце:

    def AJAX_tag_autocomplete(request): 
    if request.GET.has_key(‘q’):):): 
    tags = \
    Tag.objects.filter(name istartswith=request.GET [‘q’]) [:10]
    return HttpResponse('\n'.join(tag.name for tag in tags)) 
    return HttpResponse()
    

    Плагин autocomplete() отправляет пользовательский ввод в GET-переменную с именем q. Таким образом, мы можем убедиться, что эта переменная существует и построить список тегов, имена которых начинаются со значения этой переменной. Это сделано с помощью метода filter() и оператора istartswith, о котором мы узнали ранее в главе. Мы выберем только первые десять результатов чтобы избежать ошеломления пользователя предложениями и снизить расходы на пропускную способность и производительность. Наконец мы соединяем предложения в одну строку, разделенные знаками новой строки, переносим строки в объект HttpResponse и возвращаем его.

    Так как представление готово, добавим запись о плагине в файл, как показано ниже:

    urlpattems = patterns ('
    # AJAX
    (r'^AJAX/tag/autocomplete/$', AJAX_tag_autocomplete),
    )
    

    Теперь Активируйте плагин на поле ввода тегов, введя следующий код в файл js/tag_autocomplete.js:

    $(document).ready(function () {
    $("#id_tags").autocomplete(
    '/AJAX/tag/autocomplete/',
    {multiple: true, multipleSeparator:	1	'}
    ) ;
    }>;
    

    Код передает анонимную функцию методу $(document).ready (). Эта функция вызывает функцию autocomplete() на поле ввода тегов, передает аргументы, о которых мы говорили ранее.

    Эти несколько строк кода - все, что нам нужно для того, чтобы имплементировать автоматическое заполнение тегов. Чтобы проверить новую функцию, перейдите к http: //127.0.0.l: 8000/save/ и попробуйте ввести символ или два в поле тегов. Предложения должны появиться основе тегов доступных в вашей базе данных.

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

    Следующая лекция будет рассказывать о другой теме: мы позволим пользователям голосовать и комментировать свои любимые закладки и на первой странице нашего приложения не останется так пусто, как сейчас!

    Контрольные вопросы

  • Для чего нужен живой поиск для поиска твитов?
  • Что такое технология AJAX?
  • Перечислите приемущества технологии AJAX
  • Что такое обработчик событий?
  • Что такое jQuery?
  • Упражнения

    Упражнение 1.

    Добавьте живой поиск по твитам

    Упражнение 2.

    Измените код таким образом, чтобы результаты поиска отображались на отдельной странице

    Упражнение 3.

    Добавьте возможность поиска твитов с учетов даты

    Упражнение 4.

    Добавьте возможность регистрации пользователей

    Список тем курсовых работ

  • Прототипирование приложения для ведения блогов
  • Создание прототипа приложения для сокращения ссылок
  • Создание прототипа приложения для твитов с использованием альтернативного js-фреймворка
  • Технология AJAX как современная веб-технология
  • Создание прототипа проекта форума
  • Разработка веб-почтового клиента(прототип)
  • Создание прототипа приложения для хранения заметок
  • Создание прототипа социальной сети
  • Доработка приложения для твитов путем добавления возможности общения по электронной почте
  • Прототипирование сервиса для хранения ссылок пользователей
  • Краткие итоги

  • Создали страницу поиска твита
  • Узнали об основных возможностях AJAX
  • Дополнили приложение функцией автодополнения хэштегов
  • Узнали о методах JQuery
  • Узнали об особенностях фреймворка JQuery
  • Научились обрабатыват ьсобытия
  • Узнали о способе доступа к CSS и HTML атрибутам
  • Создали класс для поиска твитов
  • Создали js-скрипты
  • Добавили в HTML-страницы возможность выполнения js-скриптов
  • Вернуться к учебному плану