这两天在学习Google AppEngine的时候, 需要写一个小程序,就是简单的从数据库里读出数据,然后显示出来。
界面使用flex的,所以数据通信是想到了用amf,搜索到了两个python的开源产品--pyAmf和Django Amf,后来看到Django Amf更新的并不频繁,所以最后选了pyAmf。
pyAmf还有一个优点是官方网站推荐了几篇django与flex通信的文章里有一篇是中文的,哈哈。。。我喜欢中文。。。链接见
http://blog.eshangrao.com/index.php/2008/02/16/447-flexpyamfdjango
我的程序参考的也就是这篇文章,但代码写完后,程序并没有通过,而是一直报找不到服务,折腾了两天终于搞出来了。
Django 服务端,
1. 新建立一个工程testAMF,然后建立一个app--dailystory.
2. 修改settings.py
将dailystory添加到INSTALLED_APPS中。
配置数据库。
3. 工程目录中( whatidisplay 文件夹里 )的urls.py 的相关代码如下:
- from django.conf.urls.defaults import *
- import settings
-
- urlpatterns = patterns('',
- (r'^dailystory/', include('testAMF.dailystory.urls')),
- (r'^admin/', include('django.contrib.admin.urls')),
- )
from django.conf.urls.defaults import *
import settings
urlpatterns = patterns('',
(r'^dailystory/', include('testAMF.dailystory.urls')),
(r'^admin/', include('django.contrib.admin.urls')),
)
4. 在dailystory文件夹中添加一个urls.py文件
- from django.conf.urls.defaults import *
-
- urlpatterns = patterns('',
- (r'^gateway/$', 'testAMF.dailystory.amfgateway.storyGateway'),
- (r'^(.*)$', 'django.views.static.serve', {'document_root':'dailystory/flex'}),
- )
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^gateway/$', 'testAMF.dailystory.amfgateway.storyGateway'),
(r'^(.*)$', 'django.views.static.serve', {'document_root':'dailystory/flex'}),
)
5. 修改dailystory文件夹中的models.py 文件
- from django.db import models
-
- class DailyStory(models.Model):
- content = models.TextField()
-
- def __unicode__(self):
- return self.title
-
- class Admin:
- pass
from django.db import models
class DailyStory(models.Model):
content = models.TextField()
def __unicode__(self):
return self.title
class Admin:
pass
6. 在dailystory文件夹中添加一个amfgateway.py文件
- from pyamf.remoting.gateway.django import DjangoGateway
- from dailystory.models import DailyStory
-
- def getDailyStory(request):
- return DailyStory.objects.all()
-
-
- storyGateway = DjangoGateway({
- 'dailystory.getDailyStory': getDailyStory,
- })
from pyamf.remoting.gateway.django import DjangoGateway
from dailystory.models import DailyStory
def getDailyStory(request):
return DailyStory.objects.all()
storyGateway = DjangoGateway({
'dailystory.getDailyStory': getDailyStory,
})
Django的服务端就大功告成了
Flex端更简单
- <?xml version="1.0" encoding="utf-8"?>
- <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
- layout="absolute" creationComplete="initApp();">
-
- <mx:Script>
- <![CDATA[
- import flash.events.NetStatusEvent;
-
- import mx.collections.ArrayCollection;
- import mx.rpc.AsyncToken;
- import mx.rpc.AsyncResponder;
- import mx.rpc.events.FaultEvent;
- import mx.rpc.events.ResultEvent;
-
- private function initApp():void
- {
-
- var token:AsyncToken=djangoService.getDailyStory();
- token.addResponder(new AsyncResponder(onGetDailyStory,faultHandler));
- }
-
- private function onGetDailyStory(re:ResultEvent, token:Object=null):void
- {
- var stories:Array = re.result as Array;
- var storyCollection:ArrayCollection = new ArrayCollection(stories);
- yesterdayStory.text = storyCollection.getItemAt(0).content;
- }
-
- private function faultHandler(fe:FaultEvent, token:Object=null):void
- {
- trace(fe.fault.faultDetail);
- }
- ]]>
- </mx:Script>
-
- <mx:RemoteObject
- id="djangoService"
- destination="dailystory"
- showBusyCursor="true">
- </mx:RemoteObject>
-
- <mx:TextArea id="yesterdayStory" x="582" y="130" height="118" width="242"/>
- </mx:Application>
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" creationComplete="initApp();">
<mx:Script>
<![CDATA[
import flash.events.NetStatusEvent;
import mx.collections.ArrayCollection;
import mx.rpc.AsyncToken;
import mx.rpc.AsyncResponder;
import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
private function initApp():void
{
var token:AsyncToken=djangoService.getDailyStory();
token.addResponder(new AsyncResponder(onGetDailyStory,faultHandler));
}
private function onGetDailyStory(re:ResultEvent, token:Object=null):void
{
var stories:Array = re.result as Array;
var storyCollection:ArrayCollection = new ArrayCollection(stories);
yesterdayStory.text = storyCollection.getItemAt(0).content;
}
private function faultHandler(fe:FaultEvent, token:Object=null):void
{
trace(fe.fault.faultDetail);
}
]]>
</mx:Script>
<mx:RemoteObject
id="djangoService"
destination="dailystory"
showBusyCursor="true">
</mx:RemoteObject>
<mx:TextArea id="yesterdayStory" x="582" y="130" height="118" width="242"/>
</mx:Application>
然后需要在于与上述flex文件同目录中新建一个services-config.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <services-config>
- <services>
- <service id="dailyStoryService" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
- <destination id="dailystory">
- <channels>
- <channel ref="dailyStoryChannel"/>
- </channels>
- <properties>
- <source>*</source>
- </properties>
- </destination>
- </service>
- </services>
- <channels>
- <channel-definition id="dailyStoryChannel" class="mx.messaging.channels.AMFChannel">
- <endpoint uri="http://localhost:8080/dailystory/gateway/" class="flex.messaging.endpoints.AMFEndpoint"/>
- </channel-definition>
- </channels>
- </services-config>
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
<services>
<service id="dailyStoryService" class="flex.messaging.services.RemotingService" messageTypes="flex.messaging.messages.RemotingMessage">
<destination id="dailystory">
<channels>
<channel ref="dailyStoryChannel"/>
</channels>
<properties>
<source>*</source>
</properties>
</destination>
</service>
</services>
<channels>
<channel-definition id="dailyStoryChannel" class="mx.messaging.channels.AMFChannel">
<endpoint uri="http://localhost:8080/dailystory/gateway/" class="flex.messaging.endpoints.AMFEndpoint"/>
</channel-definition>
</channels>
</services-config>
在编译时注意添加编译参数-services services-config.xml
然后将编译后生成的在bin-debug文件夹中的文件复制到whatidisplay"dailystory"flex文件夹里
运行django服务器
访问
http://localhost:8080/dailystory/DailyStory.html
这里与我参考的文章不同的有两点,估计是pyAMF的更新造成的。我用的pyamf版本是0.3.1.
第一个是在amfgateway.py文件中
- storyGateway = DjangoGateway({
- 'dailystory.getDailyStory': getDailyStory,
- })
storyGateway = DjangoGateway({
'dailystory.getDailyStory': getDailyStory,
})
我在给DjangoGateway赋值时使用了
appName.method--即
dailystory.getDailyStory
据官方说这可能是个bug;)具体参看
http://www.pyamf.org/wiki/DjangoHowto中的May be some problems here
另外一处是
services-config.xml 文件中,我的
destination id 给的就是django中App的名字。如果起其他名字的话,最后flex总是得不到服务。很奇怪。