chrisw
chrisw

Reputation: 273

Many-To-Many Relationship in ndb

Trying to model a many-to-many relationship with ndb. Can anyone point to a good example of how to do this?

At here is an example of what I have at the moment:

class Person(ndb.Model):
     guilds = ndb.KeyProperty(kind="Guild", repeated=True)

class Guild(ndb.Model)
     members = ndb.KeyProperty(kind="Person", repeated=True)

     def add_person(self, person):
         self.members.append(person.key)
         self.put()
         person.guilds.append(self.key)
         person.put()

Is this the correct way to go about it? I have had a good look around but can't seem to find any good documentation on the subject.

In the datastore viewer, I can see this relationship being stored as a list of Keys, which I expect.

However, when I try to use them in the Person class methods like this:

for guild in self.guilds:

I get:

TypeError: 'KeyProperty' object is not iterable

Upvotes: 8

Views: 1932

Answers (1)

Hernán Acosta
Hernán Acosta

Reputation: 695

No. That is not the correct way to go about it.

You can model a many-to-many relationship with only one repeated property:

class Person(ndb.Model):
    guilds = ndb.KeyProperty(kind="Guild", repeated=True)

class Guild(ndb.Model):
    @property
    def members(self):
        return Person.query().filter(Person.guilds == self.key)

    def add_person(self, person):
        person.guilds.append(self.key)
        person.put()

or viceversa with:

class Person(ndb.Model):
    @property
    def guilds(self):
        return Guild.query().filter(Guild.members == self.key)

class Guild(ndb.Model):
    members = ndb.KeyProperty(kind="Person", repeated=True)

    def add_person(self, person):
        self.members.append(person.key)
        self.put()

The direction of the relationship depends on many factors (your business model, number of guilds per person, number of members per guild, etc.)

Upvotes: 14

Related Questions