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?
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')