App Engine:Google App Engine中的ReferencePropertyResolveError?

1 投票
2 回答
1094 浏览
提问于 2025-04-17 07:17

请帮我理解一下,为什么在App Engine上会出现这个错误(Python 2.5,高复制)?

Traceback (most recent call last):
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/webapp/_webapp25.py", line 703, in __call__ 
    handler.post(*groups)
File "/base/data/home/apps/s~apptest/1.354937136776013205/main.py", line 963, in post
    get_purchases_for_user(pur.user, pur.car.model)
File "/base/python_runtime/python_lib/versions/1/google/appengine/ext/db/__init__.py", line 3592, in __get__
    reference_id.to_path())
ReferencePropertyResolveError: ReferenceProperty failed to be resolved: [u'User', 374836L]

背景:这个应用是关于推荐购买汽车的。

发生时间:大约每100次交易中会出现2次,所以我真的不知道是什么时候,也不知道为什么。

在代码中,pur这个对象是这样定义的:

allPurchases = models.Purchase.all()
for pur in allPurchases:
   car = get_purchases_for_user(pur.user, pur.car.model)

我之前也放过这段代码,结果也出现了同样的错误,当然是指向这一行

logging.error("Object user: %s, Car Model %s" % {str(pur.user), pur.car.model})

所以,问题不在于get_purchases_for_user这个函数

这些是数据存储中的模型:

class User(db.Model):
    username = db.StringProperty(
        required=True)
    name = db.StringProperty(
        required=True)
    email = db.EmailProperty(
        required=True)
    password = db.StringProperty(
        required=True)

class Car(db.Model):
    model = db.StringProperty()
    name = db.StringProperty()
    year = db.DateTimeProperty()

class Purchase(db.Model):
    user = db.ReferenceProperty(User,
        collection_name='recommendations')
    car = db.ReferenceProperty(Car,
        collection_name='recommendations')
    when = db.DateTimeProperty(
        auto_now=True)

2 个回答

3

我觉得问题可能出在数据存储的高复制和缺乏保证的一致性上。根据谷歌的文档:

在高复制数据存储中,跨实体组的查询(也就是说,非祖先查询)可能会返回过时的结果。为了在高复制环境中返回强一致性的查询结果,你需要在单个实体组上进行查询。这种查询叫做祖先查询。

祖先查询之所以有效,是因为实体组是一个一致性的单位:所有操作都是应用于整个组的。祖先查询在整个实体组更新之前不会返回数据。因此,从实体组的祖先查询返回的数据是一致的。

如果你的应用程序依赖于某些查询的强一致性结果,你可能需要改变应用程序存储实体的方式。这一页讨论了在高复制数据存储中处理数据的最佳实践。接下来,我们将通过示例的留言簿应用程序来看看主/从和高复制数据存储是如何工作的。

所以实际上,你可能在查询一些刚写入的数据,但这些数据还没有在整个数据存储中传播开来。因此,当你引用这个属性时,就好像它从未存在过或者被删除了一样。

看起来你在使用 .all() 来获取数据。我建议你重新编写代码,尽量使用 GQL 和祖先查询。或者可以限制数据的时间,以便让数据有时间传播。关于祖先查询的文档: http://code.google.com/appengine/docs/python/datastore/queries.html#Ancestor_Queries

4

你的实体有一个指向 User 实体的 ReferenceProperty,但这个 User 实体并不存在了——很可能是因为它被删除了。你可以添加一些代码来捕捉这个特定的错误,然后根据你的应用程序需要来处理它。

撰写回答