1. Ajax должен работать так же просто и эффективно как Django
2. Количество кода для средних задач должно быть настолько минимальным, насколько это возможно
3. Подключить Ajax-функцию должно быть не сложнее чем написать простейшую python-функцию
Решение:
Уж не знаю кто как решает эту задачу, но я уверен что почти каждый django-разработчик сталкивался с ней хотя бы раз в жизни. Вот и я однажды задумался по этому поводу. И почему-то мне захотелось использовать в решении этой задачи RPC. Настоящий такой, красивый и простой RPC...
И не знаю бы сколько велосипедов и паровозов я еще изобрел, если бы не наткнулся на один замечательный проект. Итак, внимание... DajaxProject.com
Судя по всему, проект еще достаточно зеленый, однако пользоваться библиотеками уже вполне можно и нужно. Кстати, о птичках. На сайте есть две библиотеки:
1. Dajaxice:
Связующее ядро dajaxproject. Ее основная цель заключается в банальном асинхронном взаимодействии в рамках кода на стороне сервера Django и вашего JavaScript-кода.
Связующее ядро dajaxproject. Ее основная цель заключается в банальном асинхронном взаимодействии в рамках кода на стороне сервера Django и вашего JavaScript-кода.
2. Dajax:
Мощный инструмент для легкой и супер-быстрой разработки асинхронной логики в web-приложений с использованием Python и почти отсутствием JavaScript-кода.
Мощный инструмент для легкой и супер-быстрой разработки асинхронной логики в web-приложений с использованием Python и почти отсутствием JavaScript-кода.
Итак, инструкция по применению:
1. Качаем стабильную версию Dajaxice и Dajax. Не забываем, что ядром является именно Dajaxice, поэтому оно всему и голова.
2. Распаковываем оба архива и в каждом поочередно делаем так:
$ sydo python setup.py install
3. В Вашем settings.py ищем INSTALLED_APPS и добавляем в самый низ две строки:
INSTALLED_APPS = (
$ sydo python setup.py install
3. В Вашем settings.py ищем INSTALLED_APPS и добавляем в самый низ две строки:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
...
'dajaxice',
'dajax',
...
)
4. Смотрим, чтобы TEMPLATE_LOADERS выглядели примерно так. Если нужно, редактируем:
TEMPLATE_LOADERS = (
4. Смотрим, чтобы TEMPLATE_LOADERS выглядели примерно так. Если нужно, редактируем:
TEMPLATE_LOADERS = (
'django.template.loaders.filesystem.Loader',
'django.template.loaders.app_directories.Loader',
'django.template.loaders.eggs.Loader',
)
5. Добавляем новую переменную DAJAXICE_MEDIA_PREFIX в settings.py:
DAJAXICE_MEDIA_PREFIX="dajaxice"
6. В urls.py в самом конце добавляем новую строку:
urlpatterns = patterns('',
5. Добавляем новую переменную DAJAXICE_MEDIA_PREFIX в settings.py:
DAJAXICE_MEDIA_PREFIX="dajaxice"
6. В urls.py в самом конце добавляем новую строку:
urlpatterns = patterns('',
...
(r'^%s/' % settings.DAJAXICE_MEDIA_PREFIX, include('dajaxice.urls')),
)
7. Если необходимо, добавляем импорт в urls.py:
from django.conf import settings
8. Выбираем приложение, в котором нам нужно создать RPC-вызовы и создаем там новый модуль ajax.py. Я например, предпочитаю такие вещи хранить отдельно, поэтому создал отдельное приложение jsrpc.
9. Собственно пишем первый метод, который обработает наш AJAX-запрос:
# -*- coding: utf-8 -*-
7. Если необходимо, добавляем импорт в urls.py:
from django.conf import settings
8. Выбираем приложение, в котором нам нужно создать RPC-вызовы и создаем там новый модуль ajax.py. Я например, предпочитаю такие вещи хранить отдельно, поэтому создал отдельное приложение jsrpc.
9. Собственно пишем первый метод, который обработает наш AJAX-запрос:
# -*- coding: utf-8 -*-
from dajaxice.core import dajaxice_functions
def primer(request,message):
return_message=u'Полученное сообщение: {0}'.format(message)
return simplejson.dumps({'message':return_message})
10. В settings.py делаем так, чтобы новый метод был виден для AJAX-запросов:
DAJAXICE_FUNCTIONS = (
10. В settings.py делаем так, чтобы новый метод был виден для AJAX-запросов:
DAJAXICE_FUNCTIONS = (
'jsrpc.ajax.primer',
)
11. В шаблоне, в пределах тега пишем так:
{% load dajaxice_templatetags %}{% dajaxice_js_import %}
12. Создаем кнопку чтобы проверить работоспособность:
<input onclick="Dajaxice.jsrpc.primer('primer_callback',{'message':'Хэллоу Уорлд!'});" type="button" value="Push Me!" />
Перевожу... В onclick мы должны указать какую из подключенных функций мы будем юзать. После Dajaxice нужно указать только приложение и метод в модуле ajax.py. В нашем примере получается Dajaxice.jsrpc.primer.
11. В шаблоне, в пределах тега пишем так:
{% load dajaxice_templatetags %}{% dajaxice_js_import %}
12. Создаем кнопку чтобы проверить работоспособность:
<input onclick="Dajaxice.jsrpc.primer('primer_callback',{'message':'Хэллоу Уорлд!'});" type="button" value="Push Me!" />
Перевожу... В onclick мы должны указать какую из подключенных функций мы будем юзать. После Dajaxice нужно указать только приложение и метод в модуле ajax.py. В нашем примере получается Dajaxice.jsrpc.primer.
Далее, в качестве первого параметра указываем callback, в который возвратить данные, чтобы потом разгребать средствами JavaScript. В нашем случае - primer_callback, его мы создадим позже.
Ну и как же без набора параметров... Если мы что-то хотим передать серверу, пишем точно также как обычно передаем из сервера в шаблоны. В данном случае, мы просто передаем строку на сервер. А сервер нам должен вернуть ее же. Не забываем объявить параметр message в параметрах метода, иначе ничего не получится.
13. Напишем callback:
<script type="text/javascript">
<script type="text/javascript">
function primer_callback(data){
if(data!=Dajaxice.EXCEPTION){
alert(data.message);
}else{
alert('Error');
}
}
</script>
Обратите внимание, что мы получаем "свыше" уже сериализованные данные, что, безусловно, очень удобно.
if(data!=Dajaxice.EXCEPTION){
alert(data.message);
}else{
alert('Error');
}
}
</script>
Обратите внимание, что мы получаем "свыше" уже сериализованные данные, что, безусловно, очень удобно.
14. Должно работать:
До сих пор мы пользовались только первой библиотекой - ядром Dajaxice. Что же нам могут предложить во второй библиотеке, если итак все уже шоколадно?
Скажу от себя, что предлагают нам не совсем "правильные" вещи, хотя и достаточно удобные.
Изначально Django проектировался так, чтобы полностью исключить любую возможную логику в шаблонах. И наоборот, серверная логика не должна знать вообще о существовании шаблонов, об их устройстве и структуре HTML. Если нам захотелось поменять верстку в шаблонах, это никак не должно отражаться на серверном коде. И это правильно. То что описано ниже, напрочь противоречит всем правилам! Однако, как бы то ни было, считаю своим долгом рассказать о том "неправильном" подходе, который предлагает библиотека Dajax, а дальше - выбирайте сами.
Так как мы уже подключили практически все необходимое, остается лишь одна маленькая деталь. В скачанном и распакованном архиве django-dajax-0.8.4 идем в каталог src/ и выбираем нужную библиотеку, в зависимости от того, какой JavaScript-фреймворк мы используем в проекте. Нам доступны:
1. Dojo
2. JQuery
3. Mootools
4. Prototype
Я пользуюсь JQuery, поэтому все нижеописанное будет на ее примере, хотя отличия для других библиотек незначительные.
1. Копируем jquery.dajax.core.js в каталог MEDIA_ROOT/js/.
2. В шаблоне, в пределах тега <head></head> подключаем эту самую библиотеку:
<script type="text/javascript" src="{{ MEDIA_URL }}/js/jquery.dajax.core.js" charset="utf-8"></script>
3. Подключили. Теперь создаем кнопочку и поле для вывода, чтобы почувствовать разницу в использовании:
<input type='button' value='Push Me!' onclick="Dajaxice.jsrpc.primer2('Dajax.process');" id='knopka'>
<div id='testarea'></div>
4. Создаем метод в уже созданном модуле
# -*- coding: utf-8 -*-
from django.utils import simplejson
from dajaxice.core import dajaxice_functions
from dajax.core import Dajax
...
def primer2(request):
dajax = Dajax()
dajax.assign('#knopka','value',u'Нажато')
dajax.assign('#testarea','innerHTML',u'Бла-бла-бла')
return dajax.json()
Обратите внимание, что значения для HTML-элементов Вы указываете именно на сервере. Это то о чем я писал выше. Неудобно, но зато JavaScript всего одна строка, да и то в пределах onclick. Решайте сами, использовать или нет.
5. Ну и подключаем метод в settings.py:
DAJAXICE_FUNCTIONS = (
...
'jsrpc.ajax.primer2',
)
6. Вот собственно и все. Теперь все должно работать:
Скажу от себя, что предлагают нам не совсем "правильные" вещи, хотя и достаточно удобные.
Изначально Django проектировался так, чтобы полностью исключить любую возможную логику в шаблонах. И наоборот, серверная логика не должна знать вообще о существовании шаблонов, об их устройстве и структуре HTML. Если нам захотелось поменять верстку в шаблонах, это никак не должно отражаться на серверном коде. И это правильно. То что описано ниже, напрочь противоречит всем правилам! Однако, как бы то ни было, считаю своим долгом рассказать о том "неправильном" подходе, который предлагает библиотека Dajax, а дальше - выбирайте сами.
Так как мы уже подключили практически все необходимое, остается лишь одна маленькая деталь. В скачанном и распакованном архиве django-dajax-0.8.4 идем в каталог src/ и выбираем нужную библиотеку, в зависимости от того, какой JavaScript-фреймворк мы используем в проекте. Нам доступны:
1. Dojo
2. JQuery
3. Mootools
4. Prototype
Я пользуюсь JQuery, поэтому все нижеописанное будет на ее примере, хотя отличия для других библиотек незначительные.
1. Копируем jquery.dajax.core.js в каталог MEDIA_ROOT/js/.
2. В шаблоне, в пределах тега <head></head> подключаем эту самую библиотеку:
<script type="text/javascript" src="{{ MEDIA_URL }}/js/jquery.dajax.core.js" charset="utf-8"></script>
3. Подключили. Теперь создаем кнопочку и поле для вывода, чтобы почувствовать разницу в использовании:
<input type='button' value='Push Me!' onclick="Dajaxice.jsrpc.primer2('Dajax.process');" id='knopka'>
<div id='testarea'></div>
4. Создаем метод в уже созданном модуле
# -*- coding: utf-8 -*-
from django.utils import simplejson
from dajaxice.core import dajaxice_functions
from dajax.core import Dajax
...
def primer2(request):
dajax = Dajax()
dajax.assign('#knopka','value',u'Нажато')
dajax.assign('#testarea','innerHTML',u'Бла-бла-бла')
return dajax.json()
Обратите внимание, что значения для HTML-элементов Вы указываете именно на сервере. Это то о чем я писал выше. Неудобно, но зато JavaScript всего одна строка, да и то в пределах onclick. Решайте сами, использовать или нет.
5. Ну и подключаем метод в settings.py:
DAJAXICE_FUNCTIONS = (
...
'jsrpc.ajax.primer2',
)
6. Вот собственно и все. Теперь все должно работать:
А почему не использовать чистуюю библиотеку jQuery?
ОтветитьУдалитьЭто Вы про $.ajax и про $.post?
ОтветитьУдалитьНе, ну этого пока никто не отменял, но лично мне этот подход совсем не нравится.
Во-первых - чистотой кода ну совсем не пахнет.
Во-вторых - сериализировать все приходится руками.
В-третьих - Ловить переменные через аргументы гораздо удобнее, чем так:
if request.method == 'POST':
var = request.POST['var']
В-четвертых - при правильном подходе, с помощью Dajax можно обойтись вообще без JS-методов и callback'ов.
Этого недостаточно?
в IE6 с callback все плохо =( приходится работать с чистым jquery
ОтветитьУдалитьIE6 пора бы уже забыть.
ОтветитьУдалить