1

我有两个实体(事件和用户)。每个用户都有几个事件,但我不希望它们存储在 StructuredProperty 中,因为将来应该可以有多个创建者/管理员。现在我有一个问题,用户需要事件类来定义,反之亦然。如何实现预期的结构?

两个具有相互关系的模型。

class Event(EndpointsModel):
    _message_fields_schema = ("id", "name", "creator", 
                        "datetime", "place", "category", "participants")
    creator = ndb.KeyProperty(kind=User)
    participants = ndb.KeyProperty(kind=User, repeated=True)
    name = ndb.StringProperty()
    datetime = ndb.DateTimeProperty(auto_now_add=True)
    place = ndb.GeoPtProperty()
    category = ndb.StringProperty(choices=('all', 'drinking'))

class User(EndpointsModel):

    _message_fields_schema = ("id", "name", "password", "events")

    name = ndb.StringProperty()
    password = ndb.StringProperty()
    events = ndb.KeyProperty(kind=Event, repeated=True)

    def create_event(self, e_name, e_datetime, e_place, e_category):
        event = Event(name=e_name, creator = self.key, datetime=e_datetime, place=e_place, category=e_category)
        event.put()
        self.events.append(event)
        self.put()

    def get_events(self):
        return ndb.get_multi(self.events)

错误信息:

NameError:未定义名称“用户”

编辑 1: 我将 kind 更改为包含类名的字符串,就像 Greg 建议的那样。但它也不起作用。

class Category(EndpointsModel):
    _message_fields_schema = ("id", "name", "parent")
    name = ndb.StringProperty()
    parent = ndb.KeyProperty(kind='Category', default=None)

class Event(EndpointsModel):

    _message_fields_schema = ("id", "name", "creator", "datetime", 
                               "place", "category")

    participants = ndb.KeyProperty(kind='User', repeated=True)
    creator = ndb.KeyProperty(kind='User')
    name = ndb.StringProperty()
    datetime = ndb.DateTimeProperty(auto_now_add=True)
    place = ndb.GeoPtProperty()
    category = ndb.KeyProperty(Category)

class User(EndpointsModel):

    _message_fields_schema = ("id", "name", "password")

    name = ndb.StringProperty()
    password = ndb.StringProperty()
    events = ndb.KeyProperty(Event, repeated=True)

现在我收到以下堆栈跟踪:

ERROR    2014-01-21 09:38:39,764 service.py:191] Encountered unexpected error from ProtoRPC method implementation: BadValueError (Expected Key, got [])
Traceback (most recent call last):
  File "/home/chris/Downloads/google_appengine/lib/protorpc-1.0/protorpc/wsgi/service.py", line 181, in protorpc_service_app
    response = method(instance, request)
  File "/home/chris/Downloads/google_appengine/lib/endpoints-1.0/endpoints/api_config.py", line 1321, in invoke_remote
    return remote_method(service_instance, request)
[...]
    value = self._call_shallow_validation(value)
  File "/home/chris/Downloads/google_appengine/google/appengine/ext/ndb/model.py", line 1227, in _call_shallow_validation
    return call(value)
  File "/home/chris/Downloads/google_appengine/google/appengine/ext/ndb/model.py", line 1274, in call
    newvalue = method(self, value)
  File "/home/chris/Downloads/google_appengine/google/appengine/ext/ndb/model.py", line 1927, in _validate
    raise datastore_errors.BadValueError('Expected Key, got %r' % (value,))
BadValueError: Expected Key, got []
4

3 回答 3

3

您可以在 KeyProperty 构造函数中使用字符串来引用没有模型定义的种类:

class Event(ndb.Model):
  participants = ndb.KeyProperty(kind='User', repeated=True)
于 2014-01-20T18:38:36.300 回答
2

您不能创建对实体的此类引用。这里是一些解决方案: 1. 您必须为 Event.creator 使用普通的 StringProperty 或为 User 实例使用其他 id 2. 从类 User 中删除事件 - 您可以通过事件类的索引来访问事件 3. 使用像这样的第三实体模型:

class EventCreator(EndpointsModel):
    creator = ndb.KeyProperty(kind=User)
    event =  ndb.KeyProperty(kind=Event)

并从类用户删除创建者和从类事件删除

于 2014-01-20T18:14:02.720 回答
1

您可以在没有 kind 参数的情况下指定关键属性(它是可选的),然后在构造函数或 pre-put 挂钩或类似的东西中进行手动检查——或者甚至不用担心种类:

class Event(EndpointsModel):
    creator = ndb.KeyProperty()

    # Constructor option
    def __init__(self, *args, **kwargs):
        super(Event, self).__init__(*args, **kwargs)
        if 'creator' in kwargs and kwargs['creator'] != 'User':
            raise Exception('oh no')

    # Hook option
    _pre_put_hook(self):
        if self.creator and self.creator.kind() != 'User':
            raise Exception("oh no")

实际的语法可能会略有不同。随意编辑。

于 2014-01-21T21:22:32.390 回答