4

我又回到了 AppEngine 开发中。我对数据存储很感兴趣。

我习惯于“ids”,使用“/view?id=322345”之类的链接构建网站,让我获得了带有这个 id 的留言簿条目。

但是在 AppEngine 中,我总是看到调用 db.Key.from_path() 方法以及其他诸如“祖先”和“父母”之类的东西。

在我的项目中,我有简单的关系,比如用户->电话号码,我想通过 GET url 附加一些类似 id 的东西来检查每个用户。我应该使用 User models key() 还是在 AppEngine 中如何实现?

目前,如果我想向用户添加一个电话号码,我会写以下内容:

class JoinHandler(webapp2.RequestHandler):
    def get(self):
        user_key = self.request.get('rlm')
        fon_number = PhoneNumber()
        fon_number.country = "deDE"
        fon_number.user = db.Key(user_key)
        fon_number.put()
        self.redirect("/")
4

2 回答 2

9

如果您使用put实体时数据存储区自动分配的数字 ID,则可以使用模型的get_by_id方法检索实体:

class User(db.Model):
    name = db.StringProperty()
    # etc.

def AddUser(webapp2.RequestHandler):
    def get(self):
        newUser = User()
        newUser.name = self.request.get('name')
        # etc. assign all model properties
        newUser.put()
        # now, newUser.Key().id() contains the auto-assigned numeric id.
        # we can pass this value to our template and get it back via
        # a form paramter for subsequent operations.

def ShowUser(webapp2.RequestHandler):
    def get(self):
        user_to_show_id = self.request.get('id')
        user_to_show = User.get_by_id(user_to_show_id)
        if user_to_show is not None:
            # populate the template parameters with the users's data
            # and render the template
        else:
            # The requested user does not exist, so
            # render an error message/page.

现在,如果您还想存储属于给定用户的电话号码实体,您可以将它们存储为它们的父级是用户实体。这会将它们放在用户的实体组中,并且与将它们与父项一起存储相比,可以更快地一起查询实体组中的实体。

假设任何用户都可以有任何给定数量的 Phonenumber 实体与之关联:

class Phonenumber(db.Model):
    number_type = db.StringProperty()
    number = db.StringProperty()

我们将向 User 类添加一个方法:

def AddNumber(self, new_number_type, new_number):
    new_number = Phonenumber(parent=self, number_type=new_number_type, number=new_number)
    # In this case, self is the User entity, and by saying parent=self, we're putting
    # this Phonenumber entity into User's entity group.
    new_number.put()

def GetPhoneNumber(self):
    # Now, getting all of User's phone numbers is a simple as a query with an
    # Ancestor clause:
    users_numbers = Phonenumber.all().ancestor(self).fetch(1000)

   return users_numbers

显然,这些类是幼稚的,直接从我的脑海中浮现出来,但我希望它们能帮助你理解 id 和祖先的关系。通常,您根本不必Key()手动创建密钥。除非你真的需要,否则不要走那条路。尽管如此,了解 Keys 的工作原理对于真正了解 AppEngine 还是很有帮助的,因此如果您愿意,可以深入研究并进行试验。

我认为这是你的两个主要问题,是吗?如果您还有其他人,请继续发表评论,我将编辑我的答案。

于 2012-04-15T17:02:23.790 回答
2

至于您db.Key.from_path()要做什么的问题,请查看Key Class 文档,您会看到第一个参数from_path()是您要检索的数据存储对象的类型。

Args 是这样列出的:

Key.from_path(kind, id_or_name, parent=None, namespace=None)

在我的一个基本博客应用程序中,我有以下行:

key = db.Key.from_path('BlogPost', int(post_id), parent=blog_key())

这是在寻找一个类型为 的对象BlogPost,其 id 为post_id,并且其父对象等于该blog_key()方法的返回值。

blog_key()定义为:

def blog_key(name = 'default'):
return db.Key.from_path('blogs', name)

老实说:我还没有弄清楚这部分(从udacity cs253逐字复制),但我认为它建立的是数据存储中所有BlogPost对象的祖先值。

我只在 GAE 工作了几个星期,完成了 cs253 课程,所以我非常感谢对此的任何澄清,或者更清楚地解释“正在发生的事情”

于 2013-10-23T04:35:40.297 回答