从GAE中的NDB数据存储中获取第一条记录

时间:2016-08-29 20:12:40

标签: python google-app-engine

我目前正在使用Google App Engine for Python编写应用程序。我想获取我的数据存储区中的第一条记录,但由于某种原因,这将无法正常工作。这就是我在MySQL中的表现:

SELECT * FROM MyClass LIMIT 1;

然而,由于我是NDB的新手,我似乎无法理解这是如何运作的。我尝试阅读the documentation作为示例,但它们并不常用。

这是我目前的代码:

from google.appengine.ext.ndb import Model as NdbModel
from google.appengine.ext.ndb import StringProperty


class Model(NdbModel):

    @classmethod
    def get_first(cls):
        """
        Get the first record in the model datastore
        :return: Model
        """
        try:
            return cls.query().fetch(1)[0]
        except IndexError:
            raise ModelException("No records found in [%s] datastore" % cls.__name__)


class MyClass(Model):
    foo = StringProperty()
    bar = StringProperty()

a = MyClass.get_first() # TypeError: 'NoneType' object does not support item assignment

这是我的完整堆栈跟踪:

TypeError: 'NoneType' object does not support item assignment
    at _store_value (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py:1127)
    at _deserialize (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py:1496)
    at _from_pb (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py:3209)
    at pb_to_entity (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/model.py:691)
    at pb_to_query_result (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_rpc.py:201)
    at _process_results (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_query.py:2980)
    at __query_result_hook (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/datastore/datastore_query.py:2947)
    at get_result (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py:613)
    at _on_rpc_completion (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py:513)
    at _run_to_list (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py:995)
    at _help_tasklet_along (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py:427)
    at get_result (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/tasklets.py:383)
    at fetch (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/query.py:1218)
    at positional_wrapper (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/ext/ndb/utils.py:160)
    at get_first (/base/data/home/apps/s~project-id/v1.395271489319521947/project/core/models/utils.py:55)
    at me (/base/data/home/apps/s~project-id/v1.395271489319521947/project/core/routes/api/v1/profile.py:22)
    at dispatch_request (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1625)
    at full_dispatch_request (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1639)
    at handle_user_exception (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1544)
    at full_dispatch_request (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1641)
    at wsgi_app (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1988)
    at handle_exception (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1567)
    at wsgi_app (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:1991)
    at __call__ (/base/data/home/apps/s~project-id/v1.395271489319521947/lib/flask/app.py:2000)
    at Handle (/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/runtime/wsgi.py:267)

1 个答案:

答案 0 :(得分:1)

在您将数据写入数据存储区之后,您似乎正在尝试立即检索数据,除非您按照App Engine {{3}中的说明在每个实体上设置相同的parent key,否则这将无法正常工作文件。

要创建parent key,您可以写:

from google.appengine.ext.ndb import Key
parent_key = Key('my_data', 'version_1')

当您创建实体时,应将parent key传递给constructor

my_entity = MyKindClass(parent=parent_key, foo=foo_input, bar=bar_input)

然后,通过将parent_key类的query传递给kind方法来查询数据库:

first_result = MyKindClass.query(
            ancestor=parent_key).order(-MyKindClass.created).get()

我认为您对获取最新数据感兴趣,因此我使用order方法使用-运算符对结果进行了排序,该运算符对数据进行了降序排序。另外,我使用get方法而不是fetch(1),如果没有数据,则返回第一个查询结果或None

完整的代码将是:

import webapp2
from google.appengine.ext.ndb import (
    Model, StringProperty, DateTimeProperty, Key)


class MyKindClass(Model):
    foo = StringProperty()
    bar = StringProperty()
    created = DateTimeProperty(auto_now_add=True)


parent_key = Key('my_data', 'version_1')


class MainHandler(webapp2.RequestHandler):

    def get(self):
        foo_input = self.request.get('foo')
        bar_input = self.request.get('bar')
        if foo_input and bar_input:
            my_entity = MyKindClass(parent=parent_key,
                                    foo=foo_input, bar=bar_input)
            my_entity.put()

        first_result = MyKindClass.query(
            ancestor=parent_key).order(-MyKindClass.created).get()
        if first_result is not None:
            self.response.write('foo: %s, and bar: %s' %
                                (first_result.foo, first_result.bar))
        else:
            self.response.write('No data yet!')

app = webapp2.WSGIApplication([
    ('/', MainHandler)
], debug=True)

有关详细信息,请参阅App Engine的Storing Data in Cloud Datastore文档。