Necronet
Necronet

Reputation: 6813

Google App Engine return object with reference set

Hi I am kind of trying to get the concept behind DataStore as a No-SQL database, what I am trying to fetch is a list of object wich have been "reference" by another. As this

class Person(db.Model):
    name = db.StringProperty(required=True)

class Contact(db.Model):
    name = db.StringProperty(required=True)
    email = db.StringProperty()
    trader = db.ReferenceProperty(Person)

This works fine and they get to be saved when I use person.put() without any problem. But when I try to retrieve it and encoded as json it nevers shows me the contact as a list in fact it totally ignores it.

    persons_query = Person.all()
    persons = persons_query.fetch(50)
    data = json.encode(persons)

I would expect person to have a collection of Contact but it doesn't any ideas on how to solve this problem?

To make it clearer currently i am getting something like this:

[
 {
  name: "John Doe"
 }
]

I would like to be

[
 {
  name: "John Doe"
  contacts: [{name:"Alex", email:'[email protected]'}]
 }
]

Edit

Thanks all you were right I needed to fetch the collection of contacts there was only one issue for this is that when Contact was being encoded it recursively tried to encode the Trader object and this it's contact and so on.

So I got an obvious error recursive error, the solution to this was clearly to remove the trader object from the Contact when it's being encoded.

Upvotes: 0

Views: 187

Answers (3)

ibaguio
ibaguio

Reputation: 2368

Make a custom toJson function in your class

class Person(db.Model):
    name = db.StringProperty(required=True)

    def toJson(self):
        contact = self.contact_set #this is the default collection name for your class
        d = {"name":self.name,"contact":contact}
        return json.dumps(d)

class Contact(db.Model):
    name = db.StringProperty(required=True)
    email = db.StringProperty()
    trader = db.ReferenceProperty(Person)

then you may do the ff:

persons_query = Person.all()
persons = persons_query.fetch(50)
data = person.toJson()

Upvotes: 1

Tim Hoffman
Tim Hoffman

Reputation: 12986

To fetch all the contacts you will need to write a custom json encoder, which fetches all of the reverse of the reference property.

ReferenceProperties automatically get a reverse query. From the docs "collection_name is the name of the property to give to the referenced model class. The value of the property is a Query for all entities that reference the entity. If no collection_name is set, then modelname_set (with the name of the referenced model in lowercase letters and _set added) is used."

So you would add a method to resolve the reverse reference set query.

class Person(db.Model):
   name = db.StringProperty(required=True)
   def contacts(self):
       return self.contact_set.fetch(50)  # should be smarter than that

Then use it in your custom json encoder.

Upvotes: 1

dragonx
dragonx

Reputation: 15143

If you want to find all the contacts that include a person you will need to issue a query for it.

contacts = Contact.all().filter("trader =", person)

Upvotes: 0

Related Questions