logo
INFO2

Отношения в App Engine Один-ко-многим

Этот тип отношений легко реализуется в любой системе. Платформа App Engine обеспечивает хранение ключа стороны «один» в сущности со стороны «многие». В Питоне для этого используется поле-ссылка ReferenceProperty:

class Owner(db.Model):

name = db.StringProperty()

class Pet(db.Model):

name = db.StringProperty()

owner = db.ReferenceProperty(Owner)

Чтобы найти «владельца» для «питомца», мы обращаемся к атрибуту pet.owner, и App Engine автоматически загружает сущность, на которую мы ссылаемся. Чтобы найти всех «питомцев», ссылающихся на конкретного «владельца», достаточно выполнить следующий запрос:

pets = Pet.all().filter('owner =', owner).fetch(100)

Аналогичный результат можно получить проще: ReferenceProperty автоматически создает свойство в классе Owner для быстрого и удобного доступа к связанным данным, так что извлечь список «питомцев» можно так:

pets = Owner.owner_set.fetch(100)

По умолчанию, App Engine именует это свойство как имя поля + "_set", но вы можете задать свое собственное:

class Pet(db.Model):

name = db.StringProperty()

owner = db.ReferenceProperty(Owner, collection_name='pets')

pets = owner.pets.fetch(100)

Другой способ моделирования отношения «один-ко-многим» — это привязка сущности к родителю. В момент создания сущности ей может быть назначен родитель. При этом ключ сущности-родителя становится частью ключа-потомка и не может быть изменен в будущем. Вот как это выглядит в нашем примере:

class Owner(db.Model):

name = db.StringProperty()

class Pet(db.Model):

name = db.StringProperty()

bob = Owner(name='Bob')

felix = Pet(name='Felix', parent=bob)

owner_of_felix = felix.parent

Далее мы нигде явно не указываем связь между сущностями — она следует из указания родителя на момент создания. Когда лучше использовать привязку к родителю (parent) вместо поля-ссылки (ReferenceProperty)? Это влияет на работу транзакций: в App Engine в каждой отдельной транзакции можно оперировать сущностями только одной группы, т.е. множеством сущностей с родителем из той же группы. Если требуется, чтобы в транзакцию не попадали связанные сущности, используйте поле-ссылку. Кроме того, помните, что сущность может иметь только одного непосредственного родителя, и его ключ не может быть изменен после создания.