tags:

views:

881

answers:

2

I have the following Django and Flex code:

Django

class Author(models.Model):
  name = models.CharField(max_length=30)

class Book(models.Model):
  title = models.CharField(max_length=30)
  author = models.ForeignKeyField(Author)

Flex

package com.myproject.models.vo
{
    [Bindable]
    [RemoteClass(alias="myproject.models.Book")]

    public class BookVO
    {
        public var id:int;
        public var title:String;
        public var author: AuthorVO;
    }
}

As you can see in this example, Author is a foreign key in my Book model. Now I'd like to acccess the author's name when I call my BookVO in Flex. As such, I'd expect code like the following to work, but "author_name" results in a null:

var book = new BookVO();
var author_name = book.author.name;

I realize I could call an AuthorVO directly, but the crux of this question is how can you retrieve foreign-keyed values using Flex when your VOs are bound to a remote object? I'm currently using PyAMF to bridge the gap between Flex and Django, but I'm not sure that's relevant.

A: 

when you get your book from the database, try using select_related()

which is way down on this page:
http://docs.djangoproject.com/en/dev/ref/models/querysets/

it, "will automatically "follow" foreign-key relationships, selecting that additional related-object data when it executes its query. This is a performance booster which results in (sometimes much) larger queries but means later use of foreign-key relationships won't require database queries."

I've been loving how seamless the access to the database is through PyAMF from Flex. It's really brilliant.

Jim Carroll
Some progress. I receive the following error. Any thoughts?ReferenceError: Error #1056: Cannot create property _title_cache on com.myproject.models.vo.BookVO.
Huuuze
hmmm... I'm not sure, but the next thing I'd try is to reset and sync the database... (your current data will be deleted.)
Jim Carroll
I'll give that a shot, but I remain skeptical. Just out of curiosity, is this something you have working? To be certain, you are able to access the fields of a foreign-keyed model, correct? If so, would you mind posting an example on dpaste.com or some other site?
Huuuze
Sorry, I must not have understood the question... the Book.objects.select_related(depth=2).get(id=5) for example would follow out two levels of foreign keys, and you would have all the data passed back of AMF. If that doesn't solve it, then I'm missing the question.
Jim Carroll
BTW... I don't think you need a models.vo.Book on the Actionscript side... the receiving side of PyAMF will just get the object as an Object with sub-objects for the various fields.
Jim Carroll
In your case, if those various fields are objects themselves, you have access to each of their fields, correct? If so, please post an example.
Huuuze
+1  A: 

Ok, Here's an example...

Model:

class Logger(models.Model):
    lname = models.CharField(max_length=80)

    def __unicode__(self):
        return self.lname
    #
#

class DataSource(models.Model):
    dsname = models.CharField(max_length=80)
    def __unicode__(self):
        return self.dsname
    #
#

class LoggedEvent(models.Model):
    # who's data is this?
    who = models.ForeignKey(Logger)
    # what source?
    source = models.ForeignKey(DataSource)
    # the day (and, for some events also the time)
    when = models.DateTimeField()
    # the textual description of the event, often the raw data
    what = models.CharField(max_length=200)
    # from -1.0 to 1.0 this is the relative
    # importance of the event
    weight = models.FloatField()

    def __unicode__(self):
        return u"%2.2f %s:%s - %s" % (self.weight, self.source, self.who, self.what)
    #
#

Here's my amfgateway.py

def fetch_events(request, source):
    events = LoggedEvent.objects.select_related().all()
    return events
#

services = {
    'recall.fetch_events': fetch_events,
}

gateway = DjangoGateway(services)

and here's my Actionscript for the receiving side of the AMF call:

protected function onRetrievedEvents(result: Object): void {

    for each(var evt: Object in result) {
        var who: Object = evt._who_cache.lname;

...

The evt._who_cache.lname is populated with the select_related() and missing when the select related is missing. If I get rid of the select_related() call, then I see the error:

TypeError: Error #1010: A term is undefined and has no properties.

You must be trying a different technique with your RemoteClass... so the select_related might not be the problem at all... (otherwise my first answer wouldn't have gotten negged.) The rest is up to you.

Jim Carroll
Jim, thanks for the detailed response. Ultimately, I contacted the lead dev of PyAMF and he found a bug in how this works. As such, he's made a change that will be included in PyAMF 0.4.1. The net yield is that you won't be required to call the "_cache" attributes any longer.
Huuuze
Great! it will be nice when that _cache stuff is gone.
Jim Carroll