Доброго времени суток!
При написании данной статьи ставилась цель описать законченный пример использования двух фреймворков Flex и Django, а так же показать процесс разработки с их помощью небольшого приложения от начала и до конца.
Задача
Реализовать форму обратной связи для отсылки пользовательских сообщений администратору сайта.
Пояснение
Связка Flex и Django может показаться нерациональной для решения данной задачи, ведь с ней вполне можно справится с помощью HTML и одного скрипта на PHP. Так и есть. :) На этой небольшой задаче я постараюсь рассмотреть минимум необходимый для работы с этими замечательными фреймворками в связке.
От автора
Статья будет интересна тем, кто еще только присматривается к Flex и Django, но не пробовал их в деле. К статье прилагаются полные исходные коды сервера и клиента. Их можно скачать отсюда SendFormFlexDjango.zip. В силу специфики задачи серверная часть примера получилась очень маленькой, так что большая часть статьи описывает создание Flex клиента.
Сразу отмечу, что я не спец по Flex и Django и, к сожалению, не могу сказать, что имею серьезный опыт в web-разработке. :) Дружу с Python уже более двух лет, хотя до недавнего времени не применял для web. Год назад я столкнулся с Flex и немного работал с ним. А несколько недель назад я начал разработку небольшого проекта, для реализации клиентской части которого решил использовать Flex/ActionScript 3.0, а для сервера Django/Python. После небольшого перерыва и без груза чужой кодовой базы, можно сказать начал знакомство с Flex заново, с более свежими ощущениями. :) С Django я ранее знаком не был, и в процессе изучения был приятно удивлен удобством этого фреймворка. На мой взгляд сочетание Flex и Django позволяет довольно быстро получить практический результат.
Из вещей которые мне больше всего понравились во Flex: декларативное описание интерфейса и Data binding. Эти особенности позволяют писать гибкий код и компактный. Что понравилось в Django так это обилие возможностей "из коробки" и прекрасная документация.
О себе немного рассказал. Технологии похвалил. Пора к делу!
Что потребуется для работы?
Для разработки клиента можно взять Trial-версию Adobe Flex Builder 3.
Однако, данной статье я буду использовать бесплатные инструменты FlashDevelop + Flex SDK.
Adobe Flex 3.5 SDK
Нужен для компиляции клиента.
Страница загрузки.
FlashDevelop
Бесплатная среда разработки. На данный момент лучшая бесплатная IDE для ActionScript и Flex. В сравнении с Flex Builder 3 очень аскетичная. К сожалению, хоть она и open source, но написана под .Net, и поддерживается только под Windows. Под Mono не проверял.
http://www.flashdevelop.org
Inkscape
Этот графический векторный редактор потребуется для редактирования и экспорта макета формы из формата svg. Макет в svg находится в архиве с исходниками для статьи. http://www.inkscape.org/
Aptana Studio или Eclipse совместно с дополнением Pydev.
http://www.aptana.org/
http://pydev.org/nightly
Python 2.6
Замечательный язык программирования. ;)
http://www.python.org/
Django 1.1.1
http://www.djangoproject.com/
Django-1.1.1.tar.gz
Для отладки может понадобиться Debug версия Flash Player. Различные версии Flash Player можно скачать здесь
Я скачал Standalone версию плеера, просто закинул его в Program Files и сопоставил для открытия swf файлов.
Огорчает лишь, что по умолчанию Flash Develop не содержит встроенного отладчика и умеет отображать только вывод функции trace().
Отладочного вывода через trace() должно хватать для большинства задач.
Для вывода сложных объектов можно использовать функцию mx.utils.ObjectUtil.toString(obj).
Если же не доступна отладочная версия плеера (нельзя просмотреть вывод функции trace() ), то можно воспользоваться стандартной функцией показа сообщений mx.controls.Alert.show(msg).
Пишем клиентскую часть
Подготовка
Для разработки клиентской части нам потребуется FlashDevelop, Inkscape и Flex SDK.
Распакуем Flex SDK куда-нибудь и настроим в FlashDevelop путь к нему:
Tools->Programm Settings->AS3Context->Flex SDK Location
Шаг 1
Создадим в FlashDevelop проект Flex 3 Project с именем feedback_client (Project->New Project).

Новый проект содержит файл Main.mxml, откроем его и вставим следующий код:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="300">
<mx:VBox x="0" y="0" width="100%" height="100%" horizontalAlign="center">
<mx:HBox width="100%">
<mx:Label text="Имя" width="15%"/>
<mx:TextInput id="nameTxt" width="100%" maxChars="40" />
</mx:HBox>
<mx:HBox width="100%">
<mx:Label text="e-mail" width="15%"/>
<mx:TextInput id="emailTxt" width="100%" maxChars="40"/>
</mx:HBox>
<mx:TextArea id="msgTxt" width="100%" height="100%" maxChars="5000" />
<mx:Button id="sendBtn" label="Отправить" />
</mx:VBox>
</mx:Application>
* This source code was highlighted with Source Code Highlighter.
Описание приложения на Flex начинается с узла mx:Application.
В свойствах этого узла описываются габаритные размеры итоговой флэшl2;и и фоновый цвет. Application в программе на Flex может быть только один. Экземпляр текущего приложения всегда можно узнать из свойства mx.core.Application.application. Все остальные элементы управления добавляются как дочерние элементы Application.
В данном примере я использовал контейнеры VBox и HBox для автоматического выравнивания элементов интерфейса. Существует множество способов задавать размеры и положение объекта: x, y, left, right, top, bottom, width, height, horizontalCenter, verticalCenter. Что особенно удобно, так это возможность использования процентов для задания некоторых величин.
Для компиляции и запуска проекта нажмем F5 или кнопку на панели инструментов:

Если все в порядке, запустится Flash Player или браузер с нашим приложением:

Для простоты я не стал в примере использовать стандартные компоненты для создания форм и механизм валидации. Flex предоставляет довольно обширный набор компонентов пользовательского интерфейса. Создать простую форму для отправки сообщения не составляет труда, но с оформлением по умолчанию она смотрится слегка уныло.
Шаг 2
Попробуем исправить ситуацию, для этого добавим в наше приложение графику.
В качестве примера к статье прилагается, созданный в Inkscape, svg-файл с макетом формы отправки в виде блокнота.
Создадим в директории проекта feedback_client каталог assets в который будем помещать всю графику.
Подготовим графику для встраивания в приложение, экспортировав svg элементы макта в файлы png.
Откроем файл "notepad_src.svg" и экспортируем в png слой "Блокнот".
Для этого откроем окно со списком слоев Shift+Ctrl+L (Слой->Слои), снимем замок со слоя "Блокнот", а на остальные наоборот навесим. Выберем все Ctrl+A (Правка->Выделить все). Shift+Ctrl+E (Файл->экспортировать в растр). Нажать кнопку "Выделение" и поставить галочку экспортировать только выделение, чтобы фон не попал в растр. Выбираем где сохранить файл и жмем экспорт.

Аналогичным образом экспортируется еще три изображения разных состояний кнопки отправки.
Шаг 3
Изменим структур Main.mxml и опишем графику в css файле.
Чтобы не загромождать Main.mxml вынесем форму для ввода данных в отдельный компонент, в файл FormCanvas.mxml и создадим еще один компонент для отображения сообщений, StatusCanvas.mxml.
Cкажу пару слов о создании своих компонент.
Новые компоненты создавать в Flex проще простого. Однажды описав их в отдельном mxml файле их легко потом использовать где угодно как в других mxml так из ActionScript. Для получения нового компонента создается mxml файл и в качестве корневого узла указывается компонент от которого требуется наследоваться.
В нашем случае это будет mx:Canvas:
<?xml version="1.0" encoding="utf-8"?>
<!--src/NewComponent.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" >
<mx:Label id="mylabel" text="label"/>
</mx:Canvas>
* This source code was highlighted with Source Code Highlighter.
Внутри этого узла можно размещать любые теги с описанием элементов управления. При компиляции mxml файла создается новый ActionScript класс с именем таким же как имя файла. Для элементов с указанным свойством id, автоматически создаются публичные свойства для доступа к ним из кода ActinScript и биндинга.
Пример использования:
var nc:NewComponent = new NewComponent();
this.addChild(nc); // добавление nc на отображаемый компонент
/* отображение nc */
Alert.show(nc.mylabel.text); //допустимо но объект nc уже должен быть отображен на экране
* This source code was highlighted with Source Code Highlighter.
Если nc еще не отображен в приложении, то его дочерние элементы еще не созданы и поле mylabel будет содержать null.
Переменные будут гарантированно доступны только после события creationComplete. (Хорошее описание этого процесса flex-component-lifecycle-overview)
Если требуется передать объекту параметры сразу при создании, следует описать внутри него свои свойства или поля посредством тега mx:Script (см. StatusCanvasScript.as и StatusCanvas.mxml ), они будут инициироваться в конструкторе. Можно проводить их обработку в обработчике события creationComplete, либо, пометив как [Bindable], биндить(BindingUtils.bindProperty()) непосредственно на элементы управления. Для простоты встраивания графики подключим ее через css. Создадим директорию styles и в ней файл main.css. Опишем css классы с картинкой нашего блокнота и скины для кнопки, используя ключевое слово Embed для встраивания графики в результирующий swf файл приложения:
.notepadBg{
backgroundImage: Embed("../assets/notepad.png");
verticalScrollPolicy: off;
horizontalScrollPolicy: off;
}
.sendButton
{
upSkin: Embed("../assets/send_btn_active.png");
overSkin: Embed("../assets/send_btn_over.png");
downSkin: Embed("../assets/send_btn_down.png");
disabledSkin:Embed("../assets/send_btn_active.png");
}
* This source code was highlighted with Source Code Highlighter.
Теперь мы можем подключить наш css в любом mxml файле:
<mx:Style source="../styles/main.css"/>
И применять описанные в css классы к компонентам указывая имя класса в свойстве styleName:
<mx:Canvas styleName="notepadBg" width="400" height="500"/>
<mx:Button id="sendBtn" styleName="sendButton" />
Опишем классы для полей ввода: .textInput и .textArea.
Чтобы все выглядело натурально нужно сделать поля ввода прозрачными и убрать рамку фокуса:
.textInput
{
backgroundAlpha: 0.0;
borderStyle: none;
focusAlpha: 0;
fontFamily: "Arial";
fontSize: 16;
}
* This source code was highlighted with Source Code Highlighter.
Для textArea вдобавок увеличим расстояния между строк:
.textArea
{
/*...*/
leading:8.6;
}
* This source code was highlighted with Source Code Highlighter.
На время отладки, выставим значения backgroundAlpha и backgroundColor для удобства подгонки положения элементов:
.textArea
{
/*...*/
backgroundAlpha: 0.8;
backgroundColor: #ff0000;
/*...*/
}
* This source code was highlighted with Source Code Highlighter.
Подгоняем положение элементов экспериментируя со значениями координат и размерами элементов в FormCanvas.mxml.
После подгонки параметров получиться вот так:

Шаг 4
Выставляем backgroundAlpha равное 0 и убираем backgroundColor из стилей .textInput и .textArea.
В итоге у нас получится вполне симпатичный и интерактивный результат:


После проделанных изменений наш проект будет выглядеть так:
<?xml version="1.0" encoding="utf-8"?>
<!--src/FormCanvas.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="500" styleName="notepadBg" >
<mx:Style source="../styles/main.css"/>
<mx:VBox left="40" top="60" right="50" >
<mx:HBox width="100%">
<mx:Label text="Имя:" width="18%" styleName="label" />
<mx:TextInput id="nameTxt" width="72%" maxChars="40" styleName="textInput"/>
</mx:HBox>
<mx:HBox width="100%">
<mx:Label text="e-mail:" width="18%" styleName="label" />
<mx:TextInput id="emailTxt" width="72%" maxChars="40" styleName="textInput"/>
</mx:HBox>
<mx:TextArea id="msgTxt" width="100%" height="268" maxChars="5000" styleName="textArea" />
<mx:Canvas width="100%">
<mx:Button id="sendBtn" label="" horizontalCenter="0" styleName="sendButton" />
</mx:Canvas>
</mx:VBox>
</mx:Canvas>
* This source code was highlighted with Source Code Highlighter.
<?xml version="1.0" encoding="utf-8"?>
<!--src/Main.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:ns1="*"
width="400" height="500"
paddingLeft="0" paddingRight="0" paddingTop="0" paddingBottom="0"
horizontalScrollPolicy="off" verticalScrollPolicy="off"
>
<mx:Style source="../styles/main.css"/>
<mx:Canvas left="0" top="0" right="0" bottom="0" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<ns1:FormCanvas id="formCanvas" x="0" y="0" visible="true" />
<ns1:StatusCanvas id="statusCanvas" x="0" y="0" visible="false" />
</mx:Canvas>
</mx:Application>
* This source code was highlighted with Source Code Highlighter.
<?xml version="1.0" encoding="utf-8"?>
<!--src/StatusCanvas.mxml -->
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="400" height="500" styleName="notepadBg">
<mx:Style source="../styles/main.css"/>
<mx:Text verticalCenter="0" horizontalCenter="0" selectable="false" styleName="label"
htmlText="Сообщение" />
<mx:Text horizontalCenter="0" bottom="110" styleName="label" selectable="false"
htmlText="Кликните чтобы продолжить." />
</mx:Canvas>
* This source code was highlighted with Source Code Highlighter.
/* styles/main.css */
.notepadBg{
backgroundImage: Embed("../assets/notepad.png");
verticalScrollPolicy: off;
horizontalScrollPolicy: off;
}
.sendButton
{
upSkin: Embed("../assets/send_btn_active.png");
overSkin: Embed("../assets/send_btn_over.png");
downSkin: Embed("../assets/send_btn_down.png");
disabledSkin:Embed("../assets/send_btn_active.png");
}
.textInput
{
/*backgroundAlpha: 0.8;
backgroundColor:#ff0000;/*/
backgroundAlpha: 0.0; /*прозрачный фон*/
borderStyle: none;
focusAlpha: 0; /*убираем рамку фокуса*/
fontFamily: "Arial";
fontSize: 16;
}
.textArea
{
/*backgroundAlpha: 0.8;
backgroundColor:#ff0000;*/
backgroundAlpha: 0.0;/*прозрачный фон*/
borderStyle: none;
focusAlpha: 0; /*убираем рамку фокуса*/
fontFamily: "Arial";
fontSize: 16;
leading:8.6; /*увеличиваем междустрочный интервал*/
}
.label
{
fontFamily: "Arial";
fontSize: 16;
fontWeight :bold;
textAlign: center;
}
.labelGreen
{
fontFamily: "Arial";
fontSize: 22;
fontWeight :bold;
textAlign: center;
color:#00ff00;
}
.labelRed
{
fontFamily: "Arial";
fontSize:22;
fontWeight :bold;
textAlign: center;
color:#ff0000;
}
* This source code was highlighted with Source Code Highlighter.
Шаг 5
Интерфейс готов. Осталось написать логику обработки; и отправки данных. Для этого создадим два файла MainScript.as и StatusCanvasScript.as в которых будем писать ActionScript код для нашего приложения. Подключим их к mxml файлам добавив тег mx:Script
для Main.mxml:
<mx:Script source="MainScript.as"/>
и для StatusCanvas.mxml:
<mx:Script source="StatusCanvasScript.as"/>
После проделанных изменений FlashDevelop будет отображать наши as файлы как вложенные узлы родительских mxml в дереве проекта.

Заполним as файлы кодом:
/* MainScript.as */
import flash.events.MouseEvent;
import mx.rpc.AsyncToken;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
import mx.controls.Alert;
private static const SERVER_URL:String = "http://127.0.0.1:8081/send";
private var service: HTTPService = null;
private function complete():void
{
service = new HTTPService();
service.url = SERVER_URL;
service.method = "POST";
service.resultFormat = "text";
formCanvas.sendBtn.addEventListener(MouseEvent.CLICK, sendBtnClick, false, 0, true );
statusCanvas.addEventListener(MouseEvent.CLICK, statusCanvasClick, false, 0, true );
}
private function showStatus(status:int, msg:String = null):void {
statusCanvas.status = status;
if (msg) statusCanvas.msgHtml = msg;
statusCanvas.visible = true;
}
private function sendBtnClick(event:MouseEvent):void
{
if ((formCanvas.nameTxt.text == "") ||
(formCanvas.emailTxt.text == "")||
(formCanvas.msgTxt.text == ""))
{
showStatus(StatusCanvas.EMPTY_FORM);
return;
}
formCanvas.enabled = false;
sendForm();
}
private function sendForm():void {
var params:Object = { name:formCanvas.nameTxt.text,
email:formCanvas.emailTxt.text,
msg:formCanvas.msgTxt.text};
var token:AsyncToken = service.send(params);
var responder:mx.rpc.Responder = new mx.rpc.Responder(onResult, onFault);
token.addResponder(responder);
}
private function statusCanvasClick(event:MouseEvent):void {
formCanvas.visible = true;
statusCanvas.visible = false;
}
private function clearForm():void {
formCanvas.nameTxt.text = "";
formCanvas.emailTxt.text = "";
formCanvas.msgTxt.text = "";
}
protected function onResult(event:ResultEvent):void
{
formCanvas.enabled = true;
var xml:XML = new XML(event.result);
var code:int = int(xml.code);
switch(code) {
case 0:
showStatus(StatusCanvas.OK);
clearForm();
break;
case 1:
showStatus(StatusCanvas.MSG, xml.msg);
break;
default:
showStatus(StatusCanvas.ERROR);
}
}
protected function onFault(event:FaultEvent):void
{
formCanvas.enabled = true;
if (event.statusCode == 0)
showStatus(StatusCanvas.CONNECTION_ERROR);
else showStatus(StatusCanvas.ERROR);
}
* This source code was highlighted with Source Code Highlighter.
/* StatusCanvasScript.as */
import mx.binding.utils.BindingUtils;
public static const OK:int = 0;
public static const ERROR:int = 1;
public static const CONNECTION_ERROR:int = 2;
public static const MSG:int = 3;
public static const EMPTY_FORM:int = 4;
private var _status:int = MSG;
[Bindable]
public var msgHtml:String = "";
[Bindable]
public var msgStyleName:String = "labelGreen";
private function complete():void
{
BindingUtils.bindProperty(msgTxt,'htmlText', this, 'msgHtml');
BindingUtils.bindProperty(msgTxt,'styleName', this, 'msgStyleName');
}
public function set status(status:int):void{
_status = status;
switch(status) {
case OK:
msgStyleName = "labelGreen";
msgHtml = "Сообщение успешно<br>отправленно";
break;
case ERROR:
msgStyleName = "labelRed";
msgHtml = "Ошибка!<br>Попробуйте позднее.";
break;
case CONNECTION_ERROR:
msgStyleName = "labelRed";
msgHtml = "Сервер<br>недоступен."
break;
case EMPTY_FORM:
msgStyleName = "labelRed";
msgHtml = "Заполните<br>все поля."
break;
default:
msgHtml = "";
msgStyleName = "label";
break;
}
}
public function get status():int{
return _status;
}
* This source code was highlighted with Source Code Highlighter.
Теперь нужно обязательно указать обработчики события creationComplete="complete()" у корневых элементов в Main.mxml и StatusCanvas.mxml и наше клиентское приложение готово.
Приведу модификации в упрощенном виде:
<mx:Application сreationComplete="complete()" >
<!-- содержимое -->
<mx:Script source="MainScript.as"/>
</mx:Application>
<mx:Canvas creationComplete="complete()" >
<!-- содержимое -->
<mx:Script source="StatusCanvasScript.as"/>
</mx:Canvas>
Теперь при нажатии на кнопку Отправить мы можем насладится одним из двух сообщений.


Как видно из кода, приложение посредством обьекта класса HTTPService делает POST запрос на url http://127.0.0.1:8081/send передавая данные сообщения в переменных name, email и msg. Дело за малым написать обработчик этого запроса.
На этом с клиентом закончим, пора браться за сервер.
Пишем серверную часть
Подготовка
Установим Python, Django и Aptana Studio. Для установки Django нужно распаковать Django-1.1.1.tar.gz и выполнить:
python setup.py install
.Желательно так же добавить c:\Python26\Scripts\ в системную переменную PATH, чтобы было удобно использовать django-admin.py, который расположен по этому пути.
После этой манипуляции потребуется перезагрузка.
Создаем проект сервера
Откроем Aptana Studio и создадим новый проект для Python с именем feedback_server (File->New->Project->Pydev->Pydev Project)
Галочку с "Create default 'src'..." можно снять.

Запустим cmd.exe и перейдем в директорию проекта feedback_server. Создадим проект Django:
django-admin.py startproject server
Перейдем в созданную директорию server и создадим Django приложение feedbacks для обработки отправки сообщения:
manage.py startapp feedbacks
Обновим дерево проектов в Aptana (F5) и перейдем к свойствам проекта feedback_server(Alt+Enter). Установите кодировку проекта в utf-8 (Resources->Text file encoding) В разделе "Pydev - PYTHONPATH" нужно добавить созданную django-admin.py директорию Django проекта "feedback_server/server" (Add source folder)

В разделе "Run/Debug Settings" создаем новую конфигурацию запуска (New->Python Run).
В редакторе конфигурации запуска на вкладке Main:
- Project: feedback_server
- Main Module: ${workspace_loc:feedback_server/server/manage.py}
На вкладке Arguments:
- Program arguments: runserver 8081 --noreload
- Working directory->Other: ${workspace_loc:feedback_server/server}


При использовании sqlite в качестве СУБД, без указания "Working directory" в настройках запуска, файл базы будет искаться текущем в каталоге Aptana. А так как его там нет, будет создаваться пустой файл, что приведет к ошибке при первом же запросе к таблицам.
Настройка проекта Django
Файл settings.py
В начало файла вставим код (спасибо автору топика):
import os
def rel(*x):
return os.path.join(os.path.abspath(os.path.dirname(__file__)), *x)
* This source code was highlighted with Source Code Highlighter.
#Настроим в качестве СУБД sqlite
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'db.sqlite'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
* This source code was highlighted with Source Code Highlighter.
Для чистоты эксперимента отключим в проекте все лишнее, так как задача стоит довольно простая. :)
В списке MIDDLEWARE_CLASSES и INSTALLED_APPS закомментируем все элементы.
Добавим наше приложение "feedbacks" в INSTALLED_APPS
INSTALLED_APPS =(
'server.feedbacks',
)
В список TEMPLATE_DIRS добавим строчку :
TEMPLATE_DIRS = (
rel('templates'),
)
Шаблоны xml-ответов
В директории проекта создадим соответствующую директорию "templates"'. С двумя файлами feedback_result.xml:
<!-- feedback_result.xml -->
<r>
<code>{{code}}</code>
<msg>{{msg}}</msg>
</r>
и feedbacks.xml:
<!-- feedbacks.xml -->
<r>
<feedbacks>
{% for row in feedbacks %}
<f>
<name>{{row.name}}</name>
<email>{{row.email}}</email>
<msg>{{row.msg}}</msg>
</f>
{% endfor %}
</feedbacks>
</r>
Файл urls.py
urlpatterns = patterns('',
(r'^send/', 'feedbacks.views.send'),
(r'^feedbacks/', 'feedbacks.views.feedbacks'),
)
Модель базы данных
Опишем модель базы данных в файле "feedbacks/models.py"
# -*- coding: utf-8 -*-
# feedbacks/models.py
from django.db import models
class Feedback(models.Model):
name = models.CharField(max_length=51, null=True)
email = models.CharField(max_length=51, null=True)
msg = models.CharField(max_length=5001, null=True)
* This source code was highlighted with Source Code Highlighter.
Обработчики запросов
И наконец создадим обработчики запросов в файле "feedbacks/views.py"
# -*- coding: utf-8 -*-
from django.views.generic.simple import direct_to_template
from models import Feedback
def send(request):
data = {'code' : 0}
name = request.REQUEST.get("name", "")
email = request.REQUEST.get("email", "")
msg = request.REQUEST.get("msg", "")
if (name=="") or (email=="") or (msg==""):
data['code'] = 1
data['msg'] = "Необходимо заполните все поля"
else:
f = Feedback(name=name, email=email, msg=msg)
f.save()
return direct_to_template(request, "feedback_result.xml", data, mimetype="text/xml")
def feedbacks(request):
data = {}
data['feedbacks'] = Feedback.objects.all()
return direct_to_template(request, "feedbacks.xml", data, mimetype="text/xml")
* This source code was highlighted with Source Code Highlighter.
Создадим структуру базы данных. Для этого выполним в каталоге проекта команду:
manage.py syncdb
После создания базы данных все готово для запуска сервера. Это можно сделать двумя способами: нажав в Aptana кнопку на панели инструментов Run или Ctrl+F11, либо выполнив в каталоге проекта команду:
manage.py runserver 8081
Проверка работоспособности сервера
Перейдем в браузере по ссылке: http://127.0.0.1:8081/send?name=name&email=email&msg=msg
Видим xml файл, значит наш сервер успешно обработал запрос.
<r>
<code>0</code>
<msg></msg>
</r>
Запускаем клиента на Flex и попробуем отправить сообщение через него.


Проверим что у нас накопилось в базе:
Перейдем в браузере по ссылке: http://127.0.0.1:8081/feedbacks
<r>
<feedbacks>
<f>
<name>name</name>
<email>email</email>
<msg>msg</msg>
</f>
<f>
<name>Александр</name>
<email>alex@example.com</email>
<msg>Заработало!</msg>
</f>
</feedbacks>
</r>
Все работает!
Для просмотра полученных сообщений http://127.0.0.1:8081/feedbacks можно сделать еще одно небольшое приложение Flex для администратора.
Заключение
Ну вот и все! Надеюсь кому-нибудь моя статья будет полезна. :)
Благодарю за внимание!
Огромное спасибо за статью! Собственно, на данный момент единственный пример в инете реализации обратной связи на флексе) Вопрос: возможно ли связаться с автором, что бы задать пару вопросов? Моменты простейшие, но вызывают крайний ступор, кучу времени убил, но так и не смог реализовать(
ОтветитьУдалитьТоварищи, кому не лень, можете скинуть рабочий пример обратной связи, который присылает сообщения введеные через форму на 9527665274@mail.ru к примеру...Никаких выкрутасов с графой, просто рабочий пример) Моя электронка 9527665274@mail.ru соответственно) Заранее огромное спасибо откликнувшимся!
ОтветитьУдалить