Google App Engine - 将密钥存储到 ndb KeyProperty
Google App Engine - storing key into ndb KeyProperty
我正在使用 Google App Engine 和使用 ndb 数据存储的 webapp2 创建评论系统。我创建了一个 属性 KeyProperty,这样我就可以使用相同的键获取与 post 关联的评论。
但是,每当我尝试将 post 的密钥存储到 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 的数据库模型时,应用程序的行为符合我的要求。
这是代码。
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)
非常感谢您的帮助!
错误告诉您发生了什么:
BadValueError: Expected string, got User
如果你在回溯中再往前看一点,你会看到:
post r = Reply(content=reply_content, p_key=p_key, user=user)
在您的 Reply
class 中,您将 user
设置为 ndb.StringProperty
,但在那行代码中,您似乎传递了一个完整的 User
对象,不仅仅是一个字符串。
如果您将 Reply
的 user
属性更改为 User
类型而不是 StringProperty
,那么看起来一切都应该正常工作。
您可以使用 structured properties 完成此操作:
user = ndb.StructuredProperty(User)
更新:
看了你的评论,看来你还有问题。
您创建 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
键。 This page 在 Google 上很好地解释了如何使用 ndb
。
我正在使用 Google App Engine 和使用 ndb 数据存储的 webapp2 创建评论系统。我创建了一个 属性 KeyProperty,这样我就可以使用相同的键获取与 post 关联的评论。
但是,每当我尝试将 post 的密钥存储到 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 的数据库模型时,应用程序的行为符合我的要求。
这是代码。
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)
非常感谢您的帮助!
错误告诉您发生了什么:
BadValueError: Expected string, got User
如果你在回溯中再往前看一点,你会看到:
post r = Reply(content=reply_content, p_key=p_key, user=user)
在您的 Reply
class 中,您将 user
设置为 ndb.StringProperty
,但在那行代码中,您似乎传递了一个完整的 User
对象,不仅仅是一个字符串。
如果您将 Reply
的 user
属性更改为 User
类型而不是 StringProperty
,那么看起来一切都应该正常工作。
您可以使用 structured properties 完成此操作:
user = ndb.StructuredProperty(User)
更新: 看了你的评论,看来你还有问题。
您创建 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
键。 This page 在 Google 上很好地解释了如何使用 ndb
。