#10 Open
Repository
aburgel aburgel
Branch
default
Repository
wkornewald wkornewald
Branch
default

GAEKeyField and ancestor queries

Bitbucket cannot automatically merge this request due to conflicts.

Review the conflicts on the Overview tab. You can then either decline the request or merge it manually on your local system using the following commands:

hg update 
hg pull -r default https://bitbucket.org/aburgel/djangoappengine
Author
  1. Alex Burgel avatarAlex Burgel
Reviewers
Description

i've restructured this a bit.

1. changed how ancestor queries work to not use 'startswith' 2. new class GAEKey instead of the real appengine Key 3. a few test cases

this is pushing my python know-how a bit, so if there are better ways to do all of this, please let me know.

Comments (3)

  1. Waldemar Kornewald repo owner

    That's a good start. However, apart from the startswith/ancestor hack there's another issue: GAEKeyField shouldn't require changes to value_to_db_auto(). Otherwise you'd be allowed to pass a Key object to AutoField. Maybe GAEKeyField should just derive from Field instead of AutoField.

    There's also a bigger problem: What if you want to set the parent, but you don't want to specify an id/key_name? (i.e., they should be set automatically by the DB) That's not possible with this solution. Maybe we need a custom Key class or a custom Parent() wrapper or something like that.

    1. Alex Burgel author

      Thanks for the feedback. I'm working on some modifications now.

      I changed the ancestor hack to work as you suggest. I introduced a new class GAEKey which works with GAEKeyField. So now you can do an ancestor query like this:

      Model.objects.filter(key=GAEKey(parent=parent_model).as_ancestor())
      

      I'm not 100% sure about the names, but its close enough to work with.

      One issue that I've run into when creating a new object with an ancestor. It looks like this:

      child = ChildModel(pk=GAEKey(parent=parent_model))
      

      This causes a problem because pk is now set, even though it is not complete. So after you save child, the datastore generated key will not be set. Django only sets a new pk when the current one is None.

      Not sure what the best way to fix is. A couple of ideas:

      1. GAEKeyField.to_python() should return None when the key is not complete to trick django. This seems hackish and will probably cause trouble.

      2. Modify django itself to be a bit smarter about setting new primary keys. It seems wrong to do this, and makes it less likely that the changes will be accepted upstream.

      3. Do something with signals. I don't know much about signals so this might not work.

      4. Instead of GAEKeyField controlling a single attribute, have it control both 'pk' and a new one 'parent_pk'. Django core will only know about PK, but the appengine backend would know about the other attribute, so when inserting, the backend will do the right thing. For example:

      class Model(object):
         key = GAEKeyField(parent_key_attribute="parent_key")
      
      model = Model(parent_key=GAEKey(parent_model))
      model.key == None
      model.parent_key == GAEKey(...)
      

      5. Some other idea that I haven't thought of yet.

      Any thoughts?

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.