Unable to send object from flex to django

6 views
Skip to first unread message

Bounce

unread,
Nov 19, 2010, 7:05:20 AM11/19/10
to AmFast
Hello All,

I have been trying to use amfast with django for a couple of days now
and I have (somewhat) successfully passed objects from my DB to my
Flex client but have not succeeded in doing the reverse operation .

I was starting with a complex set of models so i decided to simplify
in order to understand where am stuck.
Note: I am new to python and django so be kind if you see some
ridiculous bit of code that makes no sense ;)

Here is my models.py without ManyToManyFields

///////////////////////////////////////////////
from django.db import models
from django.contrib.auth.models import User

class Equipment(models.Model):

name = models.CharField('Name',max_length=100)

def __init__(self, *args, **kwargs):
super(Equipment, self).__init__(*args, **kwargs)

def __unicode__(self):
return self.name


class Character(models.Model):

name = models.CharField('Name',max_length=100)

def __init__(self, *args, **kwargs):
super(Character, self).__init__(*args, **kwargs)

def __unicode__(self):
return self.name
///////////////////////////////////////////////////////////////////////////

My django_channels.py

//////////////////////////////////////////////////////////////////////////

import sys
import os
import utils
from amfast import class_def
from amfast.remoting.channel import ChannelSet
from amfast.remoting.django_channel import DjangoChannel
from models import *

channel_set = ChannelSet()
rpc_channel = DjangoChannel('amf')
channel_set.mapChannel(rpc_channel)
utils.setup_channel_set(channel_set)

class_mapper = class_def.ClassDefMapper()

equipment_def = class_def.ClassDef(Equipment, 'vos.Equipment',
('name'))
class_mapper.mapClass(equipment_def)
character_def = class_def.ClassDef(Character, 'vos.Character',
('name'))
class_mapper.mapClass(character_def)


# Assign mapper to endpoints
channel = channel_set.getChannel('amf')
channel.endpoint.encoder.class_def_mapper = class_mapper
channel.endpoint.decoder.class_def_mapper = class_mapper

//////////////////////////////////////////

And here is my controller.py

//////////////////////////////////////////

from models import *
from amfast.remoting.channel import SecurityError

class Controller(object):
def checkCredentials(self, user, password):
u = User.objects.get(username__exact=user)
if u:
if u.check_password(password):
return True
else:
raise SecurityError('Invalid credentials.')
else:
raise SecurityError('Invalid credentials.')

class CharacterController(object):
def getAllRecords(self):
results = list(Character.objects.all())
return results

def getRecordById(self,value):
result = Character.objects.get(pk=value)
return result

def getByPlayer(self,value):
results =
list(Character.objects.select_related().filter(name=value))
return results

def getEquipments(self,value):
char = value;
results = Character.objects.get(pk=char.id).equipments.all()
return value

def saveRecord(self,value):
item = value
item.save()
return item

def deleteRecord(self,value):
item = value
item.delete()
return item

////////////////////////////////////////////////////////////

So in Flex when i try to create a Character object

c = new Character()
c.name="foo"
characterModel.save(c) // calls the remote object's save method which
maps to saveRecord in the py controller

i get the following error stack:

# ---- EXCEPTION DESCRIPTION BEGIN ---- #
# ---- Type ---- #
AttributeError
# ---- Detail ---- #
'Character' object has no attribute '_state'
# ---- Traceback ---- #
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/AmFast-0.5.3_r535-py2.7-macosx-10.5-fat3.egg/
amfast/remoting/__init__.py", line 221, in invoke
self.body[0].invoke(request, self)
-
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/AmFast-0.5.3_r535-py2.7-macosx-10.5-fat3.egg/
amfast/remoting/flex_messages.py", line 291, in invoke
msg.response_msg.body.body = target.invoke(packet, msg, self.body)
-
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/AmFast-0.5.3_r535-py2.7-macosx-10.5-fat3.egg/
amfast/remoting/__init__.py", line 143, in invoke
return self.callable(*args)
-
File "/Users/bounce/Documents/_DEVELOPER/PYTHON/Django/amfM2M/../
amfM2M/amfm2m/controller.py", line 35, in saveRecord
item.save()
-
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/django/db/models/base.py", line 434, in save
self.save_base(using=using, force_insert=force_insert,
force_update=force_update)
-
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/django/db/models/base.py", line 446, in
save_base
using = using or router.db_for_write(self.__class__,
instance=self)
-
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/
python2.7/site-packages/django/db/utils.py", line 133, in _route_db
return hints['instance']._state.db or DEFAULT_DB_ALIAS

# ---- EXCEPTION DESCRIPTION END ---- #
[19/Nov/2010 05:53:59] "POST /amf HTTP/1.1" 200 500

I don't understand the 'Character' object has no attribute '_state' ??

I would appreciate any help you guys can provide !

Cheers,
B.

limscoder

unread,
Nov 20, 2010, 10:28:38 AM11/20/10
to AmFast
The object is missing the '_state' attribute that the Django ORM adds
to help manage database operations. If you can identify how Django
creates that attribute, you can add it manually, in a custom ClassDef
class.

-Dave

Bounce

unread,
Nov 20, 2010, 10:40:05 AM11/20/10
to AmFast
Thanks Dave, will check it out and post back my results.

Cheers,
Bounce.

limscoder

unread,
Nov 20, 2010, 10:54:42 AM11/20/10
to AmFast
I took a look at the Django source code, and it looks like '_state' is
setup in the model's __init__ method. AmFast's default ClassDef
implementation does not call __init__ when an object is decoded (to
avoid side-affects and missing required arguments). It looks like you
will need to extend AmFast's ClassDef class and override the
'getInstance' method. The overridden method should call __init__
instead of __new__. This will require that your model classes __init__
methods do not have required arguments and do not cause side-affects.

If I can find some time, I will start working on an implementation,
but I don't know when that will be.

-Dave

limscoder

unread,
Nov 20, 2010, 10:56:42 AM11/20/10
to AmFast
I opened ticket #71 to deal with this issue: http://code.google.com/p/amfast/issues/detail?id=71

On Nov 20, 8:40 am, Bounce <anthony.janss...@gmail.com> wrote:

Bounce

unread,
Nov 20, 2010, 12:22:45 PM11/20/10
to AmFast
Thanks dave, I answered on the ticket itself with regards to your
suggestion.

I have another question which is probably more complicated than the
first:

Django's ORM manages relationships as you know. I am interested in
serializing the Many2Many relationship in AMF3.
As it stands a model defined in Django has a <Many2Many...> object
representing the related records. I would like to be able to obtain,
after decoding, an AS3 class that has an Array containing the related
records.
Any idea on how I could go about this? Where can i start looking?
Should i consider overriding the encoder and decoders?

Any pointer would be greatly appreciated.

Cheers,
Bounce.

Dave Thompson

unread,
Nov 20, 2010, 3:22:41 PM11/20/10
to amf...@googlegroups.com
Encoding the related entities is fairly straight forward:

def encode_m2m(self, val):
    return [item for item in val.all()]

encode_types = {'related_set': encode_m2m}

cd = class_def.ClassDef(MyClass, 'mapped.name', ('related_set'), encode_types=encode_types) 



If you also want to decode the values, you'll need a little extra magic.

def decode_m2m(self, val):
    m2m = ManyTooManyRel()
    # Do some magic here to properly initialize the ManyToMany object
    return m2m

decode_types = {'related_set': decode_m2m}

cd = class_def.ClassDef(MyClass, 'mapped.name', ('related_set'), decode_types=decode_types)

-Dave

--
You received this message because you are subscribed to the Google Groups "AmFast" group.
To post to this group, send email to amf...@googlegroups.com.
To unsubscribe from this group, send email to amfast+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/amfast?hl=en.


Anthony Janssens

unread,
Nov 20, 2010, 3:41:34 PM11/20/10
to amf...@googlegroups.com
Thank you Dave that is brilliant!

This does reach my python limitations though and I am stuck on something silly: how do you pass val to encode_m2m?

When using your code i get the following error:

encode_m2m() takes exactly 2 arguments (1 given)

Thanks,
Bounce

Anthony Janssens

unread,
Nov 20, 2010, 4:00:17 PM11/20/10
to amf...@googlegroups.com
FYI here is my utils.py : 

import sys
import os
import utils
from amfast import class_def
from myclassdef import MyClassDef
from amfast.remoting.channel import ChannelSet
from amfast.remoting.django_channel import DjangoChannel
from models import *

channel_set = ChannelSet()
rpc_channel = DjangoChannel('amf')
channel_set.mapChannel(rpc_channel)
utils.setup_channel_set(channel_set)

def encode_m2m(self, val):
    return [item for item in val.all()]

encode_types = {'equipments': encode_m2m}

class_mapper = class_def.ClassDefMapper()
equipment_def = MyClassDef(Equipment, 'vos.Equipment', ('name','price'))
class_mapper.mapClass(equipment_def)
character_def = MyClassDef(Character, 'vos.Character', ('name','gender','equipments'), encode_types=encode_types)
class_mapper.mapClass(character_def)


# Assign mapper to endpoints
channel = channel_set.getChannel('amf')
channel.endpoint.encoder.class_def_mapper = class_mapper
channel.endpoint.decoder.class_def_mapper = class_mapper


Cheers,
Bounce
On 20 Nov 2010, at 21:22, Dave Thompson wrote:

Anthony Janssens

unread,
Nov 20, 2010, 4:07:57 PM11/20/10
to amf...@googlegroups.com
Aha found it ! Had to remove self from the encode_m2m method ! ... SWEET!

Thanks Dave,
B.
On 20 Nov 2010, at 21:22, Dave Thompson wrote:

Dave Thompson

unread,
Nov 20, 2010, 6:41:39 PM11/20/10
to amf...@googlegroups.com
The 'val' argument is passed automatically. You're probably getting the error because the sample implementation I sent mistakenly has a 'self' argument, which would hold the reference to the calling object if the function was a bound method. If you're using the function outside of a class, it's signature should be:

def encode_m2m(val):

-Dave

Anthony Janssens

unread,
Nov 20, 2010, 6:45:51 PM11/20/10
to amf...@googlegroups.com
Understood, thanks again for your all your help and your efforts, amfast is excellent!

B.

Patrick Lemiuex

unread,
Jan 30, 2011, 8:42:38 AM1/30/11
to amf...@googlegroups.com
This would be great to see a full example of this working since django
is actually fab.

On Sat, Nov 20, 2010 at 6:45 PM, Anthony Janssens

Reply all
Reply to author
Forward
0 new messages