在Google App Engine中,有一个ListProperty这样的东西允许您保存项目的列表(数组)。您还可以指定所持项目的类型,例如字符串,整数或其他。
Google App Engine还允许您拥有ReferenceProperty。 ReferenceProperty“包含”对另一个Google App Engine模型实体的引用。如果访问ReferenceProperty,它将自动检索引用指向的实际实体。这很方便,因为它可以获取密钥,然后获取所述密钥的实体。
但是,我没有看到任何像ListReferenceProperty(或ReferenceListProperty)这样的东西。我想保留一个对其他实体的引用列表,当我尝试访问列表中的元素时,它会自动解析。我能得到的最接近的是保存db.Key对象列表。我可以使用这些密钥然后从服务器手动检索其关联的实体。
这有什么好的解决方案吗?基本上,我希望能够对其他实体进行(自动解除引用)引用的集合。我可以通过向其他实体提供一系列密钥来实现这一目标,但我希望它“知道”这些是关键项目,并且可以将它们作为服务取消引用给我。
谢谢
答案 0 :(得分:13)
第一步:
使用db.ListProperty(db.Key)创建关系。您希望ListProp位于将在“多对多”关系中具有较少引用的实体上。这也将为您提供背面参考。所以:
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)
答案 1 :(得分:6)
你是对的,没有内置ReferenceListProperty
。可以自己编写一个 - 自定义属性子类通常相当容易 - 但是当涉及到引用和缓存引用列表时,正确的做法比你想象的要难。
但是,您可以使用db.ListProperty(db.Key)
,它允许您存储密钥列表。然后,您可以使用批处理db.get()
操作单独加载或一次加载它们。这需要您自己执行解决步骤,但它也可以让您更好地控制何时取消引用实体。