Search code examples
google-app-engine

collection_name for ndb.KeyProperty


db.ReferenceProperty allowed for a collection_name argument that specified how the reference object R could query for the objects that contain R as a reference.

I don't see a similar argument for ndb.KeyProperty. How do folks get around that?


Solution

  • It took a little getting used to when I made the switch to ndb, but it is actually simpler. The collection_name is just syntactic sugar for a query, and you can do the query yourself:

    MyEntity(ndb.Model):
        a_key = ndb.KeyProperty()
    
    entities = MyEntity.query(MyEntity.a_key == some_key)
    

    Below you can see a fuller example from this Google group which creates a new @property on the referenced class (the "one";; the Post in this case) instead of on the referencing class (the "many"; the Comment in this case):

    OLD db:

    class Post(db.Model):
        content = db.TextProperty(required = True)   
       
    class Comment(db.Model):
        """ Comment object with many-to-one relationship """
        content = db.TextProperty(required = True) 
        post = db.ReferenceProperty(Post, collection_name='comment_set')
    

    NEW ndb:

    class Post(ndb.Model):
        content = ndb.TextProperty(required = True)   
    
        @property
        def comment_set(self):
            return Comment.query(Comment.post == self.key)
    
    class Comment(ndb.Model):
        """ Comment object with many-to-one relationship """
        content = ndb.TextProperty(required = True) 
        post = ndb.KeyProperty(kind=Post)
    

    If your Model classes are in separate files, you might need to change the approach to avoid circular imports

    You could use a GQL Query String in the @property:

        @property
        def comment_set(self):
            return ndb.gql('SELECT * FROM Comment WHERE post = :1').bind(self.key)
    

    Or you could use the string 'Post' for the kind argument, instead of the class Post, to avoid circular imports:

        post = ndb.KeyProperty(kind='Post')