三年前,用过AmfPHP与Flash/Flex Remoting做过交互,最近接触Python,公司项目用的Flex做前端,所以接触了PyAmf。PyAmf本质上跟AmfPHP是雷同的。都是通 过对AMF协议(ActionScript Message Format)协议的支持来实现对Flash的交互过程。
一、首先,简单的介绍一下AMF协议格式。
AMF是Adobe独家开发出来的通信协议,它采用二进制压缩,序列化、反序列化、传输数据,从而为Flash 播放器与Flash Remoting网关通信提供了一种轻量级的、高效能的通信方式。AMF最大的特色在于可直接将Flash内置对象,例如Object, Array, Date, XML,传回服务器端,并且在服务器端自动进行解析成适当的对象,这就减轻了开发人员繁复工作,同时也更省了开发时间。它采用二进制编码,可以高度压缩数 据,因此非常适合用来传递大量的资料。数据量越大,Flash Remoting的传输效能就越高,远远超过Web Service以及使用纯文本的传输方式的XML。
AMF协议是基于Http协议的,它的处理过程大致如下:
1、从客户端获取Http请求(Request)流。
2、对流进行反序列化(Deserialize),得到服务器端程序能够识别的数据,并建立响应(Response)消息。
3、找到相应的远程服务
4、调用服务器端方法,对流进行各种处理得到返回值。
5、序列化响应流
6、将序列化响应流发送Http响应给客户端。
二、安装配置PyAmf和Django
PyAmf目前的稳定版本是0.3,去官方网站下载压缩包,解压文件,执行python setup.py install 即可完成安装。
至于Django的安装配置,我前面的文章已经讲过了,详细请参阅http://www.kokkowon.cn/archives/33。
下面我们来开发具体的实际应用。首先简单介绍下pyAMF.django的处理机制。
Pyamf通过pyamf.remoting.gateway.django模块来实现与django Request、Response相对应处理机制。其中pyamf.remoting.gateway.django.DjangoGateway类是整 个处理流程的主干。我们仅仅需要在django中建立一个DjangoGateway的实例,这个实例通过urlmap对应到响应的处理函数,将把从底层 传递过来的Request解码,并映射到响应的Python对象,然后执行注册的RPC方法,返回一个Response,然后采用AMF协议格式将 Response编码,返回给django,django通过它本身的相关机制,将这个Response以http响应的方式返回给客户端。
1)创建DjangoGateway
首先创建Django项目,然后创建一个应用程序,我这里还叫做app应用,
django-admin.py startproject fortest
python manage.py startapp app
我前面的文章已经讲过了,详细请参阅http://www.kokkowon.cn/archives/33。
定义数据库模型:
app/models.py用于定义我们的数据库模型,将其修改如下:
- """
- 数据库模型
- @see: U{Django homepage (external)<http://djangoproject.com>}
- @author: U{kokko won<kokko313@gmail.com>}
- @since: 0.1.0
- """
- from django . db import models
- import datetime
- #Mysql Text类型
- class MysqlTextField ( models . Field ) :
- def db_type ( self ) :
- return ' text '
- class Favorite :
- TYPE_CHOICES = (
- ( ' url ' , ' 网址 ' ) ,
- ( ' music ' , ' 音频 ' ) ,
- ( ' video ' , ' 视频 ' ) ,
- )
- type = models . CharField ( ' 类型 ' , max_length = 30 , db_index = True , choices = TYPE_CHOICES )
- title = models . CharField ( ' 标题 ' , max_length = 250 )
- body = models . CharField ( ' 内容 ' , default = '' , max_length = 255 )
- general = MysqlTextField ( ' 描述 ' , default = '' , blank = True )
- created = models . DateTimeField ( ' 添加时间 ' , default = datetime . datetime . now , blank = True )
- def __unicode__ ( self ) :
- return self . title
- class UserFavorite ( Favorite , models . Model ) :
- user_id = models . CharField ( ' 用户ID ' , max_length = 250 , db_index = True )
- type = Favorite . type
- title = Favorite . title
- body = Favorite . body
- general = Favorite . general
- created = Favorite . created
- class Meta :
- db_table = ' user_favorites '
- verbose_name = ' 用户收藏夹 '
- verbose_name_plural = ' 用户收藏夹列表 '
以上定义了一个叫做user_favorites的表。关于Django里面model的定义说明请查看这里:http://docs.djangoproject.com/en/dev/
接着在settings.py中激活我们的app应用(应用名称为:fortest.users),将其中的INSTALLED_APPS修改如下:
- INSTALLED_APPS = (
- ' django.contrib.auth ' ,
- ' django.contrib.contenttypes ' ,
- ' django.contrib.sessions ' ,
- ' django.contrib.sites ' ,
- ' fortest.app ' ,
- )
配置数据库,修改settings.py中的:
- DATABASE_ENGINE = ' mysql ' # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
- DATABASE_NAME = ' test ' # Or path to database file if using sqlite3.
- DATABASE_USER = ' root ' # Not used with sqlite3.
- DATABASE_PASSWORD = '' # Not used with sqlite3.
- DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3.
- DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3.
返回到工程根目录,执行以下命令,自动创建表结构:
python manage.py syncdb
django会自动在test数据库中创建user_favorites表。
初始数据的写入
现在我们可以利用Django提供的API来方便的写入我们的一些初始数据。
运行以下命令,进入交互的Python Shell:
python manage.py shell
执行如下脚本
- #导入我们前面定义的model类
- >>> from fortest . app . models import UserFavorite
- #创建新记录
- >>> uf = UserFavorite ( user_id = ' kokko ' , type = 1 , title = ' fortest ' , body = ' http:// ' , general = ' none thing ' )
- >>> uf . save ()
- #...依次导入多条数据
- #取出所有用户的收藏数据
- >>> UserFavorite . objects . all ()
- [ < UserFavorite : 163 >, < UserFavorite : sohu >, < UserFavorite : 163 >, < UserFavorite :
- 163 >, < UserFavorite : 163 >,< UserFavorite : fortest > ]
更多的Django API信息请查看http://docs.djangoproject.com/en/dev/
接着在我们的Django工程目录下(app目录下)创建一个amfgateway.py文件,内容如下:
- from pyamf . remoting . gateway . django import DjangoGateway
- from models import UserFavorite
- """
- save用户收藏
- """
- def save_user_favorite ( id , user_id , _type , _title , _body , general = '' ) :
- if id == 0 :
- userFavorite = UserFavorite ( user_id = user_id , type = _type , title = _title , body = _body , general = general )
- else :
- userFavorite = UserFavorite ( id = id , user_id = user_id , type = _type , title = _title , body = _body , general = general )
- userFavorite . save ()
- return userFavorite
- """
- 添加用户收藏
- """
- def add_user_favorite ( request , user_id , _type , _title , _body , general = '' ) :
- return save_user_favorite ( 0 , user_id , _type , _title , _body , general )
- """
- 修改用户收藏
- """
- def edit_user_favorite ( request , id , user_id , _type , _title , _body , general = '' ) :
- return save_user_favorite ( id , user_id , _type , _title , _body , general )
- """
- 用户收藏夹列表
- """
- def user_favorite ( request , field = '' , value = '' ) :
- if field == ' type ' :
- rs = UserFavorite . objects . filter ( type = value )
- elif field == ' user_id ' :
- rs = UserFavorite . objects . filter ( user_id = value )
- else :
- rs = UserFavorite . objects . all ()
- return rs
- """
- 注册App网关
- """
- appGateway = DjangoGateway ( {
- ' adduserfavorite ' : add_user_favorite ,
- ' edituserfavorite ' : edit_user_favorite ,
- ' userfavorite ' : user_favorite
- } )
打开$work_root/fortest/urls.py,添加(r’^app/gateway/’, ‘fortest.app.amfgateway.appGateway’),以定义AMF网关的访问URL,用于Flex端访问。示例配置如下:
- # coding: utf-8
- from django . conf . urls . defaults import *
- # Uncomment the next two lines to enable the admin:
- from django . contrib import admin
- admin . autodiscover ()
- urlpatterns = patterns ( '' ,
- # Example:
- # (r'^fortest/', include('fortest.foo.urls')),
- ( r ' ^$ ' , ' fortest.app.views.index ' ) ,
- ( r ' ^app/ ' , include ( ' fortest.app.urls ' )) ,
- ##这里是新添加的配置
- ( r ' ^app/gateway/ ' , ' fortest.app.amfgateway.appGateway ' ) ,
- # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
- # to INSTALLED_APPS to enable admin documentation:
- # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
- # Uncomment the next line to enable the admin:
- ( r ' ^admin/(.*) ' , admin . site . root ) ,
- )
至此,终于告一段落了,接下来就是对应用进行测试了。
2)测试PyAmf
在fortest目录下,新建c.py
- from pyamf . remoting . client import RemotingService
- import sys
- gateway = RemotingService ( ' http://localhost:8000/app/gateway/ ' )
- adduserfavorite_service = gateway . getService ( ' adduserfavorite ' )
- edituserfavorite_service = gateway . getService ( ' edituserfavorite ' )
- userfavorite_service = gateway . getService ( ' userfavorite ' )
- """
- #添加用户收藏
- """
- rs = adduserfavorite_service ( ' kokko ' , ' 网址 ' , ' 163 ' , ' http://www.163.com ' )
- print rs [ ' id ' ]
- print " ---------------------------- "
- #编辑用户收藏
- rs = edituserfavorite_service ( 2 , ' wwq ' , ' 视频 ' , ' sohu ' , ' http://www.sohu.com ' )
- print rs
- print " ---------------------------- "
- #用户收藏列表
- rs = userfavorite_service ( ' user_id ' , ' kokko ' )
- for _item in rs :
- print _item . title + ' ' + _item . type + ' ' + _item . user_id + ' ' + _item . body
- print " ---------------------------- "
- sys . exit ( 0 )
运行服务器:manage.py runserver
运行测试程序:python c.py 将显示响应结果,如下图示例:
证明测试完全通过,flex端可以使用相关接口和服务器进行通讯了。由于时间关系,我这里不再给出Flash端的实例,等有时间再行补上。
参考
http://pyamf.org/
http://wiki.woodpecker.org.cn/moin/NewEdit
http://www.donews.net/limodou
http://blog.eshangrao.com/2008/02/16/447/