Google App Engine for Python中的参考列表

时间:2011-01-18 01:29:49

标签: python google-app-engine

在Google App Engine中,有一个ListProperty这样的东西允许您保存项目的列表(数组)。您还可以指定所持项目的类型,例如字符串,整数或其他。

Google App Engine还允许您拥有ReferenceProperty。 ReferenceProperty“包含”对另一个Google App Engine模型实体的引用。如果访问ReferenceProperty,它将自动检索引用指向的实际实体。这很方便,因为它可以获取密钥,然后获取所述密钥的实体。

但是,我没有看到任何像ListReferenceProperty(或ReferenceListProperty)这样的东西。我想保留一个对其他实体的引用列表,当我尝试访问列表中的元素时,它会自动解析。我能得到的最接近的是保存db.Key对象列表。我可以使用这些密钥然后从服务器手动检索其关联的实体。

这有什么好的解决方案吗?基本上,我希望能够对其他实体进行(自动解除引用)引用的集合。我可以通过向其他实体提供一系列密钥来实现这一目标,但我希望它“知道”这些是关键项目,并且可以将它们作为服务取消引用给我。

谢谢

2 个答案:

答案 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()操作单独加载或一次加载它们。这需要您自己执行解决步骤,但它也可以让您更好地控制何时取消引用实体。