Pyamf register_class not mapping strongly typed objects as expected

318 views Asked by At

I'm using Pyamf as my backend for my Flex app and I'm seeing some weird problems with the mapping of the stongly typed classes.

Here is the model that I'm returning

class MilestonActBase(RewardActBase):

    def __unicode__(self):
        return self.milestone.title

    class Meta:
        abstract = True

class SouvenirAct(MilestonActBase):
    souvenir = models.ForeignKey(Souvenir)
    group = models.ForeignKey(Group, blank=True, null=True)
    def __unicode__(self):
        return self.souvenir.title

Here is my method that returns the objects in my views.py:

try:
    pyamf.register_class(Souvenir,  'com.rain.dennys.services.vo.Souvenir')
    pyamf.register_class(SouvenirAct,  'com.rain.dennys.services.vo.SouvenirAct')
except ValueError:
    print "Classes already registered"

@login_required
def get_souvenir_acts(http_request):
    user = http_request.user
    souvenirActs = SouvenirAct.objects.filter(user=user)
    return souvenirActs

Here is my AS3 class:

package com.rain.dennys.model
{
    [RemoteClass (alias="com.rain.dennys.services.vo.SouvenirAct")]
    [Bindable]
    public class SouvenirAct extends RewardActBase
    {
        public var souvenir:Souvenir;
        public function SouvenirAct()
        {
        }
    }
}

When I call the service, I get back and array of anonymous objects, even though I've done the register_class in python and RemoteClass in Flex. So that doesn't make sense to me. I must be doing something wrong?

In playing around with it, I've tried a few different things. One thing that kinda worked was to iterate on the array in Flex and cast the items as SouvenirAct objects like so:

private function onResult(r:Array):void
{
    for each(var o:Object in r)
    {
        var c:SouvenirAct = o as SouvenirAct;
    }
}

When I do that in Flex, I get my SouvenirAct objects are typed as they should be, BUT then the child souvenir objects are all null. So when I force the casting of the SouvenirAct objects in the return result, I get null for the child properties that are strongly typed.

Has anyone see this before? Is there a different way I should be mapping classes?

2

There are 2 answers

0
b-ryce On BEST ANSWER

So I'm now pretty certain the problem was with the netConnection class. I switched it out so I could use RemoteObject, and now everything works exactly as expected.

This is how I was connecting:

netConnection.connect("http://127.0.0.1:8000/gateway/");
netConnection.addEventListener(NetStatusEvent.NET_STATUS, onError);
var responder:Responder = new Responder(onResult, handleFault);

Then I switched to what is described here: http://www.adobe.com/devnet/flex/articles/flex_django.html If anyone else runs into this, and you are using netConnection, my advice is to go with RemoteObject

1
Jonathan Rowny On

Okay, so this is kind of a guess but this has stung me a few times. Have you ever instantiated an instance of Souvenir anywhere in your flex application? If not... AS did not bother to compile it and you'll get anonymous objects back.

When you do your onResult looping block of code, it works because you're instantiating an object of SouvenirAct, but never instantiating a Souvenir (child), so it's still null because ActionScript never compiled it...Try this before your service call

//TODO: remove me later
var imjustheretocompile:Souvenir = new Souvenir();
var alsoCompileMetoo:SouvenirAct = new SouvenirAct();

Now since you've created an instance of SouvenirAct, it should actually be compiled into your app. This is usually never a problem since we presume you will be using that class at some point, then you can go back and remove the imjustheretocompile and alsoCompileMetoo variables.