【问题标题】:Google App Engine - storing key into ndb KeyPropertyGoogle App Engine - 将密钥存储到 ndb KeyProperty
【发布时间】:2016-10-05 02:03:54
【问题描述】:

我正在使用 Google App Engine 和使用 ndb 数据存储的 webapp2 创建一个评论系统。我创建了一个属性 KeyProperty,这样我就可以使用相同的键获取与帖子关联的 cmets。

但是,每当我尝试将帖子的密钥存储到 ndb.KeyProperty 中时,我都会收到一条错误消息。我尝试将 KeyProperty 更改为

p_key= ndb.KeyProperty(Post), 
p_key= ndb.KeyProperty(kind="Post"), 
p_key= ndb.KeyProperty(kind=Post, repeated=True) but none of these worked.

当我使用带有 ReferenceProperty 的 db 模型时,该应用程序的行为符合我的预期。

这是代码。

def question_key(name = 'default'):
    return ndb.Key('questions', name)

class Post(ndb.Model):
    question = ndb.StringProperty(required = True)
    created = ndb.DateTimeProperty(auto_now_add = True)
    last_modified = ndb.DateTimeProperty(auto_now = True)
    user = ndb.StringProperty()

    def render(self):
        self._render_text = self.question.replace('\n', '<br>')
        return render_str("post.html", p = self)

class Reply(ndb.Model):
    content = ndb.TextProperty(required = True)
    p_key= ndb.KeyProperty(kind=Post)
    user = ndb.StringProperty()
    created = ndb.DateTimeProperty(auto_now_add = True)
    last_modified = ndb.DateTimeProperty(auto_now = True)

    def render(self):
        self._render_text = self.content.replace('\n', '<br>')
        return self._render_text

class PostPage(Handler):
    def get(self, post_id):
        key = ndb.Key('Post', int(post_id), parent=question_key())
        post = key.get()

        params = dict(post=post)
        #retrieve all the comments and then filter it by key
        if Reply.query():
            reply = Reply.query(Reply.p_key == key)
            params['reply'] = reply

        if self.user:
            params['current_user'] = self.user.name

        if not post:
            self.error(404)
            return

        self.render("permalink.html", **params)

    def post(self, post_id):
        reply_content = self.request.get('reply')
        p_key = self.request.get('p_key') #get post key from template
        user = self.user

        if reply_content:
            r = Reply(content=reply_content, p_key=p_key, user=user)
            r.put()

            self.redirect('/stories/%s' % str(post_id))

        else:
            error = "error"
            self.redirect('/stories/%s' % str(post_id))

class NewPost(Handler):
    def get(self):
        if self.user:
            self.render("newpost.html")
        else:
            self.redirect("/login")

    def post(self):
        if not self.user:
            self.redirect('/')

        question = self.request.get('question')
        user=self.user.name

        if question:
            p = Post(parent = question_key(), question = question, user=user)
            p.put()
            self.redirect('/stories/%s' % str(p.key.id()))
        else:
            error = "error"
            self.render("newpost.html", error=error)

app = webapp2.WSGIApplication([('/', MainPage),
                           ('/stories/([0-9]+)', PostPage),
                           ('/stories/newpost', NewPost),
                           ], 
                            debug=True)

以下是错误信息。

Traceback (most recent call last):
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "/Users/young-junpark/kloupod-143223/main.py", line 240, in post
    r = Reply(content=reply_content, p_key=p_key, user=user)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2947, in __init__
    self._set_attributes(kwds)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 2993, in _set_attributes
    prop._set_value(self, value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1145, in _set_value
    value = self._do_validate(value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1092, in _do_validate
    value = self._call_shallow_validation(value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1284, in _call_shallow_validation
    return call(value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1331, in call
    newvalue = method(self, value)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/ndb/model.py", line 1781, in _validate
    (value,))
BadValueError: Expected string, got User(key=Key('users', 'default', 'User', 5629499534213120), created=datetime.datetime(2016, 10, 4, 23, 12, 27, 1990), email=u'youngtheabsolute@gmail.com', name=u'\ubc15\uc6a9\uc900', pw_hash=u'JsIho,9c9f5b4b3a19213e8a84318db6d2e94179678d2d7f22cce6af9b30a558423b28', verification_code=u'12345', verified=False)

非常感谢您的帮助!

【问题讨论】:

  • 看起来Reply.userStringProperty,但您传递的是User 实例...
  • 什么是“问题”?对于ndb.Key(),第一个参数应该是扩展ndb.Model() 的另一个类的名称。类通常以大写字母开头,您提供的代码中没有“问题”类,但您在 question_key 函数中引用了它。
  • @Jalepeno112 所以它曾经是 def question_key(name = 'default'): return db.Key.from_path('questions', name) 这只是一个虚拟父级,在 db 模型中完美运行.但是当我尝试将其迁移到 ndb 模型时,我开始遇到所有这些错误。原始代码来自我参加的一门课程。父键的解释请看链接discussions.udacity.com/t/…
  • 所以我想我已经明白了,但是如果没有完整的错误回溯,这很难。您创建ndb.Key("Post", post_id, parent=question_key()),然后将其发送到PostPage.get() 中的模板。这个键在模板中变成了一个字符串。您将该密钥发送回PostPage.post()。因此,当您尝试使用该键创建 Reply 时,它无法说它期望 ndb.Key 而是收到一个看起来像键的字符串。您应该考虑使用urlsafe 键。解释了here
  • @Jalepeno112 成功了!非常感谢你的帮助!对此,我真的非常感激!我刚刚了解了 db 和 ndb 之间的主要区别。度过一个美好的夜晚!

标签: python google-app-engine google-cloud-datastore webapp2 google-app-engine-python


【解决方案1】:

错误告诉你发生了什么:

BadValueError: Expected string, got User

如果你再往回看一点,你会看到:

post r = Reply(content=reply_content, p_key=p_key, user=user) 

在您的Reply 类中,您将user 设置为ndb.StringProperty,但在该代码行中,您似乎传递的是一个完整的User 对象,而不仅仅是一个字符串。

如果您将Replyuser 属性更改为User 类型而不是StringProperty,那么看起来一切正常。

您可以使用structured properties 完成此操作:

user = ndb.StructuredProperty(User)

更新: 看了你的cmets,看来你又遇到了问题。

您创建ndb.Key("Post", post_id, parent=question_key()),然后将其发送到PostPage.get() 中的模板。该键在模板中编码为字符串,如下所示:

u"Key('question', 'default', 'Post', 123123213123)

我假设您将该密钥发送回PostPage.post()。因此,当您尝试使用该密钥创建Reply 时:

r = Reply(content=reply_content, p_key=p_key, user=user)

它没有说它期望ndb.Key,而是收到了一个看起来像键的字符串。您应该考虑使用urlsafe 键。 Google 上的This page 很好地解释了如何使用ndb

【讨论】:

  • 非常感谢。我仍然收到错误 BadValueError: Expected Key, got u"Key('questions', 'default', 'Post', 5838406743490560)" 这是我不明白的部分,因为我认为这是指一个假人parent def question_key(name = 'default'): return ndb.Key('questions', name) 我错过了祖先的东西吗?
  • 有趣。所以这是一个与question_key 函数的返回值相关的新错误。看起来p = Post(parent = question_key(), question = question, user=user) 快要死了。但是该错误使question_key 似乎返回一个字符串,而不是 ndb.Key()。
猜你喜欢
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2013-01-10
  • 1970-01-01
  • 2017-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多