1

我们的团队对 AppEngine 来说相对较新,我们仍在学习中。我们使用普通的 ndb.Model 模型(即没有什么花哨的)和 webapp2 处理程序。该应用程序没有 UI,因为它只是一个安静的 API。

所以我们有一个这样定义的模型:

from google.appengine.ext import ndb
class Pasta(ndb.Model):
 type = ndb.StringProperty(indexed=True)
 name = ndb.StringProperty()
 contents = ndb.JsonProperty()
 modified_date = ndb.DateTimeProperty(auto_now=True)
 added_date = ndb.DateTimeProperty(auto_now_add=True)

用例是,如果一条记录不存在,我们想添加一条记录,如果确实存在,则返回它。我们可以在处理程序中查询它,甚至在那里创建一个并使用pasta.put()实例方法创建一个新的。但是,我们认为数据绑定代码属于模型,而不是处理程序,但是,如果我们没记错的话,在模型上下文中我们需要使用 ,get_or_insert()这需要我们显式声明一个 Key,对吗?

有什么建议如何在模型中处理这种逻辑?TIA。

4

3 回答 3

1

我不知道您为什么认为代码是否进入模型或处理程序的决定决定了您用于执行查询的方法。您可以get_or_insert在任何一个地方使用,但这确实意味着您需要知道所需实体的密钥。而且,您可以在任何一个地方进行查询。

如果您确实希望将所有数据交互保留在模型中,一种可能的模式是在模型上定义一个类方法,该方法执行查询并返回现有实例或新实例。就像是:

class Pasta(ndb.Model): 
    ...
    @classmethod
    def get_or_create(cls, type=None, name=None):
        query = cls.query(cls.type=type, cls.name=name)
        existing = query.get()
        if existing:
            return existing
        else:
            new_item = cls(type=type, name=name)
            new_item.put()
            return new_item

(注意我实际上并没有使用 ndb,但这或多或少是正确的。)您需要确保在事务中调用此方法。

于 2012-11-13T16:51:34.213 回答
0

对于为什么创建实例(或记录)属于模型,您有一个非常奇怪的论点。

是的,模型代表数据,但处理程序是负责创建模型实例的人。您没有提供足够的信息来说明您的处理程序所做的事情。

首先,您需要确定要用作密钥的内容。如果您只是使用 ndb 随机创建的密钥,我不知道您将如何确定记录是否存在。我假设您想使用 Pasta.type 或 Pasta.name 作为键。

在这种情况下,“类型”或“名称”可能会作为参数提供给您的处理程序,并且您的处理程序将在根据其参数构造键后调用 get_or_insert。

我也可以将您的问题解释为您只需要给定 Pasta 模型的一条记录。这将是相当非典型的数据存储使用,但在这种情况下,在模型中使用方法来检查单个实例是否存在可能是有意义的。在这种情况下,您可以硬编码您的密钥。

于 2012-11-13T17:28:14.380 回答
0

密钥访问比查询更快且成本更低。在实现查询之前始终确定您不能使用 ID 是个好主意。此外,请记住所有模型属性的默认索引状态为 True,因此无论何时设置模型,始终声明 indexed=True/False 是一个非常好的主意。在很多情况下,人们忘记了默认值为 True,然后想知道为什么他们的索引存储在只查询少量属性时会变得非常大。您是否想要其他模型属性的索引?

于 2012-11-13T18:55:47.490 回答