RHSeeger
RHSeeger

Reputation: 16262

GAE: Model loses track of parent->child relationship

I'm having what seems like a very strange problem with an Entity relationship in the google app engine data store. I'm work on a Python/GAE webapp (learning exercise), the full code to which can be found on sourceforge.

Now this is where the weird part comes in... If I change a file (any file I've tested on) or even just update the timestamp of the file (ie, so it gets reloaded)... the ".photos" attribute of galleries starts failing. For example, if I try to load the page for the "flowers" gallery:

Traceback (most recent call last):
  File "C:\Applications\Google\google_appengine\google\appengine\ext\webapp\__init__.py", line 700, in __call__ handler.get(*groups)
  File "C:\Eclipse-Workspace\galleries-google\app\views\gallery.py", line 33, in get for photo in gallery.photos:
AttributeError: 'Gallery' object has no attribute 'photos'

I can restart the webapp, I can restart the app launcher and then start the webapp. The problem persists regardless of this. It seems I need to force the datastore to "remember" the connection in some way

# Reading the list of photos for a given gallery via the Photo entity
# This seems to force the datastore to "remember" the connection between the two
from google.appengine.ext import db
import pprint
from app.models.gallery import Gallery
from app.models.photo import Photo

gallery = Gallery.get_by_key_name('candy')
print("Gallery: " + gallery.search_term)
q = db.GqlQuery("SELECT * FROM Photo WHERE gallery = :1", gallery )
photos = q.fetch(20)

for photo in photos :
    print("\tphoto: " + photo.getUrl('original'))

or by re-ingesting all the data from scratch (though I suppose even just re-ingesting a single gallery would do).

Does anyone have any thoughts as to what might be causing this? Any help would be appreciated.

Notes:

Upvotes: 2

Views: 155

Answers (1)

RHSeeger
RHSeeger

Reputation: 16262

So, after much digging around, I believe I found an answer...

  • When a file is modified (the timestamp changes), the app engine invalidates the compiled/cached files it has
  • When the Photo class is defined, it adds a property to the Gallery based on the collection of ids it has for them
  • When it needs the Gallery class, the app engine reloads the code for it... because it's definition was invalidated by a file being modified
  • Since it doesn't know it needs the Photo class, it doesn't load that file, so the "new instance" of the Gallery class doesn't have the property that should be created for it's collection

My first solution was to add a dependency on the Photo file in the Gallery file.

from app.models.photo import Photo

The problem with this is that it creates a circular dependency between the two files (since Photo already needs to know about Gallery in order to have a list of them). While it worked, I was told that Python has "problems" with circular dependencies, and it's probably not a good thing to do; it may come back to bite me later.

The solution I wound up going with was to have the __init.py file for the package in question include a dependency for both files. As such, any time either one of the files is needed, both will be loaded.

Upvotes: 2

Related Questions