Список ссылок в Google App Engine для Python
В Google App Engine есть такая вещь, как ListProperty, которая позволяет хранить список (массив) элементов. Вы также можете указать тип удерживаемого элемента, например string, integer или что-то еще.
Google App Engine также позволяет вам иметь ReferenceProperty. ReferenceProperty "содержит" ссылку на другую модель модели Google App Engine. Если вы обратитесь к ReferenceProperty, он автоматически получит фактическую сущность, на которую ссылаются ссылки. Это удобно, поскольку он бьет получение ключа, а затем получает объект для указанного ключа.
Однако я не вижу такой вещи, как ListReferenceProperty (или ReferenceListProperty). Я хотел бы провести список ссылок на другие объекты, которые будут автоматически разрешены при попытке доступа к элементам в списке. Самое близкое, что я могу получить, похоже, состоит в том, чтобы удерживать список объектов db.Key. Я могу использовать эти ключи, а затем вручную извлекать связанные с ними объекты с сервера.
Есть ли хорошее решение? В принципе, я хотел бы иметь возможность иметь набор ссылок (для автоматического разыменования) для других объектов. Я почти добираюсь туда, имея набор ключей к другим объектам, но я хотел бы, чтобы он "знал", что это ключевые элементы, и что он может разыменовать их как услугу для меня.
Спасибо
Ответы
Ответ 1
Шаг первый:
Используйте db.ListProperty(db.Key) для создания отношения. Вы хотите, чтобы ListProp был в Entity, который будет иметь меньшее количество ссылок в отношениях Many to Many. Это также даст вам обратную ссылку. Итак:
class Spam
prop1 = db.String
eggs = db.List
class Eggs
prop1 = db.string
@property
def spams(self):
return Spam.all().filter('eggs', self.key())
Это дает ссылки в обоих направлениях.
Шаг второй:
Создайте метод utlility, который устраняет свойства.
def prefetch_refprops(entities, *props):
"""Dereference Reference Properties to reduce Gets. See:
http://blog.notdot.net/2010/01/ReferenceProperty-prefetching-in-App-Engine
"""
fields = [(entity, prop) for entity in entities for prop in props]
ref_keys = [prop.get_value_for_datastore(x) for x, prop in fields]
ref_entities = dict((x.key(), x) for x in db.get(set(ref_keys)))
for (entity, prop), ref_key in zip(fields, ref_keys):
prop.__set__(entity, ref_entities[ref_key])
return entities
Использование:
derefrenced_spams = prefetch_refprops(Spams, models.Spam.eggs)
Ответ 2
Вы правы, там нет встроенного ReferenceListProperty
. Можно было бы написать один из них - пользовательские подклассы свойств обычно довольно просты - но правильное их решение сложнее, чем вы думаете, когда дело доходит до отсрочки и кеширования списка ссылок.
Однако вы можете использовать db.ListProperty(db.Key)
, который позволяет вам хранить список ключей. Затем вы можете загрузить их по отдельности или сразу, используя пакетную операцию db.get()
. Это требует, чтобы вы сами делали шаг разрешения, но он также дает вам больше контроля при разыменовании объектов.