Search code examples
pythongoogle-app-enginegoogle-cloud-datastorereferenceproperty

How to access items in a model with ReferenceProperty?


This is a follow up on my previous question.

I set up the models with ReferenceProperty:

class User(db.Model):
    userEmail = db.StringProperty()

class Comment(db.Model):
    user = db.ReferenceProperty(User, collection_name="comments")
    comment = db.StringProperty(multiline=True)

class Venue(db.Model):
    user = db.ReferenceProperty(User, collection_name="venues")
    venue = db.StringProperty()

In datastore I have this entry under User:

Entity Kind: User
Entity Key: ag1oZWxsby0xLXdvcmxkcgoLEgRVc2VyGBUM
ID: 21
userEmail: [email protected]

And under Venue:

Entity Kind: Venue
Entity Key: ag1oZWxsby0xLXdvcmxkcgsLEgVWZW51ZRhVDA
ID: 85
venue (string): 5 star venue
user (Key): ag1oZWxsby0xLXdvcmxkcgoLEgRVc2VyGBUM
User: id=21

I am trying to display the item in hw.py like this

query = User.all()
    results = query.fetch(10)
    self.response.out.write("<html><body><ol>")
    for result in results:
        self.response.out.write("<li>")
        self.response.out.write(result.userEmail)
        self.response.out.write(result.venues)
        self.response.out.write("</li>")
    self.response.out.write("</ol></body></html>")

This line works:

        self.response.out.write(result.userEmail)

But this line does not work:

        self.response.out.write(result.venues)

But as per vonPetrushev's answer result.venues should grab the venue associated with this userEmail.

Sorry if this is confusing: I am just trying to access the tables linked to the userEmail with ReferenceProperty. The linked tables are Venue and Comment. How do I access an item in Venue or in Comment? Thanks.


Solution

  • venues is actually a query object. So you'll need to fetch or iterate over it.

    Try replacing the self.response.out.write(result.venues) line with a loop:

    query = User.all()
    users = query.fetch(10)
    self.response.out.write("<html><body><ol>")
    for user in users:
        self.response.out.write("<li>")
        self.response.out.write(user.userEmail)
        self.response.out.write("<ul>")
        # Iterate over the venues
        for venue in user.venues:
            self.response.out.write("<li>%s</li>" % venue.venue)
        self.response.out.write("</ul></li>")
    self.response.out.write("</ol></body></html>")
    

    However, this will not scale very well. If there are 10 users, it will run 11 queries! Make sure you are using Appstats to look for performance issues like these. Try to minimize the number of RPC calls you make.

    A better solution might be to denormalize and store the user's email on the Venue kind. That way you will only need one query to print the venue information and users email.