Last two weeks, i was trying to figure how to work with Django + PyAMF with Flex front end. Seems to be not enough examples for new users. Finally i got an example from amfphp – “Flex Contacts” to start with, and bit of changes made flex to interact with django backend thru pyamf.
Let’s start from django.
1. models.py (Usual django model declaration)
class Contact(models.Model):
contact_fname = models.CharField(max_length=100)
contact_lname = models.CharField(max_length=100)
contact_email = models.CharField(max_length=100)
contact_url = models.CharField(max_length=100)
class Meta:
ordering = ["contact_fname"]
verbose_name = "Contact"
verbose_name_plural = "Contact's"
def __unicode__(self):
return self.contact_fname
After doing changes to model.py, make sure to run “python manage.py syncdb” to create contact table in the database.
2. Create a file “gateway.py” under your project_name/app_name/
#import the required pyamf and django modules
from pyamf.remoting.gateway.django import DjangoGateway
import pyamf
from django.core.exceptions import ObjectDoesNotExist
# import your model
from app_name.models import Contact
# need to register your django models to provide alias (mapping)
# to Flex models
pyamf.register_class(Contact, 'com.example.model.ContactVO')
# To get all Contacts
def getContacts(request):
return Contact.objects.all()
# To update and create a new contact, the create/update from flex
# would be return as class object. so it can be save/update directly
# Please check for pyamf.register_class
def saveContact(request, data):
try:
obj = Contact.objects.get(id=data.id)
data.save()
except ObjectDoesNotExist:
obj = Contact(contact_fname=data.contact_fname,
contact_lname=data.contact_lname,
contact_email=data.contact_email,
contact_url=data.contact_url)
obj.save()
return obj.id
# To remove a contact, get the contact id from flex
def removeContact(request, id):
try:
obj = Contact.objects.get(id=id)
obj.delete()
except ObjectDoesNotExist:
pass
return id
# Finally to expose django views use DjangoGateway
gw = DjangoGateway({
"ContactService.getContacts": getContacts,
"ContactService.saveContact": saveContact,
"ContactService.removeContact": removeContact
})
3. Add the following lines in url.py
from app_name import gateway
# add in the urlpatterns
(r'^gateway/$', gateway.gw),
4. To start django development server, run “python manage.py runserver”.
5. To check the pyamf connection, create a python_test.py
and add the following.
# pyamf has RemotingService act as a client for AMF calls
from pyamf.remoting.client import RemotingService
gw = RemotingService('http://127.0.0.1:8000/gateway/')
#To get service proxy for ContactService, which is defined in the gateway.py
service = gw.getService('ContactService')
# To check the objects available in the model
print service.getContacts()
6. Run "python python_test.py" to get the output.
The flex code was taken from http://jonniespratley.com/ with minor
changes to fit with this example,
Thanks to the author for easier example to start with flex.
7. Create a flex project - FlexContact and here is the FlexContact.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
width="1024" height="768" creationComplete="init()">
<mx:Script>
<![CDATA[
import com.example.model.ContactVO;
import mx.collections.ArrayCollection;
import mx.utils.ArrayUtil;
import mx.controls.Alert;
[Bindable] private var contactCollection:ArrayCollection;
[Bindable] private var selectedContact:ContactVO;
private var connection:NetConnection;
private var gateway:String = "http://localhost:8000/gateway/";
private function init():void
{
connection = new NetConnection();
connection.connect(gateway);
getContacts();
}
//Load this function every action like create/update/remove, so that it gets all the contacts
private function getContacts():void
{
connection.call("ContactService.getContacts",
new Responder(onResult_contacts, onFault));
}
//Create a new contact or update selected contact
private function saveContact():void
{
if (selectedContact == null)
{
//Create a new Contact
var newContact:ContactVO = new ContactVO();
newContact.id = 0;
newContact.contact_fname = txt_fname.text;
newContact.contact_lname = txt_lname.text;
newContact.contact_email = txt_email.text;
newContact.contact_url = txt_url.text;
connection.call("ContactService.saveContact",
new Responder( onResult, onFault), newContact);
clearContact();
} else {
var updateContact:ContactVO = new ContactVO();
updateContact.id = selectedContact.id;
updateContact.contact_fname = txt_fname.text;
updateContact.contact_lname = txt_lname.text;
updateContact.contact_email = txt_email.text;
updateContact.contact_url = txt_url.text;
connection.call("ContactService.saveContact",
new Responder( onResult, onFault), updateContact);
clearContact();
}
}
private function clearContact():void
{
selectedContact = new ContactVO();
dg_contacts.selectedItem = null;
txt_fname.text = "";
txt_lname.text = "";
txt_email.text = "";
txt_url.text = "";
}
private function selectHandler(event:Event):void
{
selectedContact = event.target.selectedItem as ContactVO;
}
private function removeContact():void
{
if (selectedContact != null)
{
connection.call("ContactService.removeContact",
new Responder( onResult, onFault ), selectedContact.id );
}
}
private function onResult_contacts(data:Object):void
{
contactCollection = new ArrayCollection( ArrayUtil.toArray(data) );
}
private function onFault(data:Object):void
{
Alert.show( "Service Error" );
}
private function onResult(data:Object):void
{
getContacts();
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%">
<mx:ApplicationControlBar width="100%">
<mx:Label text="Flex Contact Manager" fontSize="18" fontWeight="bold" />
<mx:Spacer width="100%" />
<mx:Button label="Refresh" click="getContacts()" />
<mx:Button label="Remove" click="removeContact()" />
</mx:ApplicationControlBar>
<mx:HDividedBox width="100%" height="100%">
<mx:Panel title="Contact Details" width="100%" height="100%" layout="horizontal" cornerRadius="10">
<mx:Form width="100%" height="100%" cornerRadius="10">
<mx:FormHeading label="Contact Information" />
<mx:FormItem label="ID:" width="100%">
<mx:Label text="{selectedContact.id}" />
</mx:FormItem>
<mx:FormItem label="First Name: " width="100%" required="true">
<mx:TextInput id="txt_fname" text="{selectedContact.contact_fname}" width="100%" />
</mx:FormItem>
<mx:FormItem label="Last Name: " width="100%" required="true">
<mx:TextInput id="txt_lname" text="{selectedContact.contact_lname}" width="100%" />
</mx:FormItem>
<mx:FormItem label="Email : " width="100%" required="true">
<mx:TextInput id="txt_email" text="{selectedContact.contact_email}" width="100%" />
</mx:FormItem>
<mx:FormItem label="URL: " width="100%" required="true">
<mx:TextInput id="txt_url" text="{selectedContact.contact_url}" width="100%" />
</mx:FormItem>
<mx:FormItem label="" direction="horizontal" width="100%">
<mx:Button label="Clear" click="clearContact()" />
<mx:Button label="Save" click="saveContact()" />
</mx:FormItem>
</mx:Form>
</mx:Panel>
<mx:Panel title="Contacts" width="100%" height="100%" layout="vertical" alpha="1.0">
<mx:DataGrid id="dg_contacts" width="100%" height="100%"
change="selectHandler(event)" dataProvider="{contactCollection}">
<mx:columns>
<mx:DataGridColumn headerText="ID" dataField="id" width="50" />
<mx:DataGridColumn headerText="First Name" dataField="contact_fname" />
<mx:DataGridColumn headerText="Last" dataField="contact_lname" />
<mx:DataGridColumn headerText="Email" dataField="contact_email" />
<mx:DataGridColumn headerText="URL" dataField="contact_url" />
</mx:columns>
</mx:DataGrid>
</mx:Panel>
</mx:HDividedBox>
</mx:VBox>
</mx:WindowedApplication>
8. The Contact Model was defined as
package com.example.model
{
[RemoteClass(alias="com.example.model.ContactVO")]
[Bindable]
public class ContactVO
{
public var id:int;
public var contact_fname:String;
public var contact_lname:String;
public var contact_email:String;
public var contact_url:String;
}
}
9. Make sure to start the django development server,
Hopefully the application has to work after flex compilation.
print service.getContacts()
Read Full Post »