Google app engine 如何解决ndb模型中的某种鸡卵关系?
我有两个实体事件和用户。每个用户都有几个事件,但我不希望它们存储在StructuredProperty中,因为将来应该可以有多个创建者/管理员。现在我遇到了一个问题,用户需要事件类进行定义,反之亦然。如何实现预期的结构 具有相互关系的两个模型 类EventEndpointsModel: _消息\u字段\u架构=id、名称、创建者、, 日期时间、地点、类别、参与者 creator=ndb.KeyPropertykind=User 参与者=ndb.KeyPropertykind=User,重复=True name=ndb.StringProperty datetime=ndb.DateTimePropertyauto\u now\u add=True 地点=ndb.GeoPtProperty category=ndb.StringPropertychoices='all','Drughing' 类UserEndpointsModel: _消息\u字段\u架构=id、名称、密码、事件 name=ndb.StringProperty password=ndb.StringProperty events=ndb.KeyPropertykind=Event,repeated=True def创建事件自身、事件名称、事件日期时间、事件地点、事件类别: event=Eventname=e_name,creator=self.key,datetime=e_datetime,place=e_place,category=e_category event.put self.events.appendevent 自我推销 def get_事件本身: 返回ndb.get\u multiself.events 错误消息: NameError:未定义名称“用户” 编辑1: 我将种类更改为字符串,包含类名,就像Greg建议的那样。但它也不起作用 类别类别和点模型: _消息\u字段\u架构=id、名称、父项 name=ndb.StringProperty parent=ndb.KeyPropertykind='Category',默认值=None 类EventEndpointsModel: _消息\字段\模式=id、名称、创建者、日期时间、, 地点、类别 参与者=ndb.KeyPropertykind='User',重复=True creator=ndb.KeyPropertykind='User' name=ndb.StringProperty datetime=ndb.DateTimePropertyauto\u now\u add=True 地点=ndb.GeoPtProperty 类别=ndb.KeyPropertyCategory 类UserEndpointsModel: _消息\u字段\u架构=id、名称、密码 name=ndb.StringProperty password=ndb.StringProperty events=ndb.KeyPropertyEvent,repeated=True 现在,我收到以下堆栈跟踪:Google app engine 如何解决ndb模型中的某种鸡卵关系?,google-app-engine,app-engine-ndb,endpoints-proto-datastore,protorpc,Google App Engine,App Engine Ndb,Endpoints Proto Datastore,Protorpc,我有两个实体事件和用户。每个用户都有几个事件,但我不希望它们存储在StructuredProperty中,因为将来应该可以有多个创建者/管理员。现在我遇到了一个问题,用户需要事件类进行定义,反之亦然。如何实现预期的结构 具有相互关系的两个模型 类EventEndpointsModel: _消息\u字段\u架构=id、名称、创建者、, 日期时间、地点、类别、参与者 creator=ndb.KeyPropertykind=User 参与者=ndb.KeyPropertykind=User,重复=Tr
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 []
不能创建对实体的此类引用。以下是somo解决方案: 1.必须为Event.creator使用普通StringProperty,或为用户实例使用其他id 2.从类用户中删除evens-您可以通过类事件的索引访问evens 3.使用第三个实体模型,如下所示:
class EventCreator(EndpointsModel):
creator = ndb.KeyProperty(kind=User)
event = ndb.KeyProperty(kind=Event)
从类用户删除创建者和从类事件删除,您不能创建对实体的此类引用。以下是somo解决方案: 1.必须为Event.creator使用普通StringProperty,或为用户实例使用其他id 2.从类用户中删除evens-您可以通过类事件的索引访问evens 3.使用第三个实体模型,如下所示:
class EventCreator(EndpointsModel):
creator = ndb.KeyProperty(kind=User)
event = ndb.KeyProperty(kind=Event)
从类用户删除创建者和从类事件删除,您可以使用KeyProperty构造函数中的字符串来引用没有模型定义的种类:
class Event(ndb.Model):
participants = ndb.KeyProperty(kind='User', repeated=True)
您可以在KeyProperty构造函数中使用字符串来引用没有模型定义的种类:
class Event(ndb.Model):
participants = ndb.KeyProperty(kind='User', repeated=True)
您可以在不使用种类参数的情况下指定键属性,这是可选的,然后在构造函数或预置挂钩中进行手动检查或类似操作,或者甚至不必担心种类:
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")
实际语法可能会略有不同。请随意编辑。您可以在不使用种类参数的情况下指定密钥属性,这是可选的,然后在构造函数或预置挂钩或类似的东西中进行手动检查,或者甚至不必担心种类:
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")
实际语法可能会略有不同。请随意编辑。您可以创建/定义一个KeyProperty,它引用其他类,这些类可以通过将种类指定为字符串来创建循环依赖性。看另一个答案。很好,我不知道这个功能。坦克斯·蒂姆。我认为这是最好的选择。你可以创建/定义一个KeyProperty,它引用其他类,这些类可以通过将种类指定为字符串来创建循环依赖性。看另一个答案。很好,我不知道这个功能。坦克斯·蒂姆。我觉得这是最好的选择。好吧,这听起来不错,但似乎不起作用。我收到以下异常:引发数据存储\u错误。BadValueError'预期的键,获取%r'%value,BadValueError:预期的键,获取[]首先需要保存一个用户实例,然后将其放置,您将分配该键而不是对象。ie event.participants=some_user.key,则其工作正常-因此,在上面的create_event代码中,您需要执行self.events.appendevent.keydb.ReferenceProperty支持的对象分配,但ndb.KeyProperty将只接受一个键。我添加了您的更改,文件现在看起来像这样,但错误仍然存在。get/insert和delete可以正常工作,但我无法接收
我对所有用户都毫无例外。好吧,这听起来不错,但似乎不起作用。我收到以下异常:引发数据存储\u错误。BadValueError'预期的键,获取%r'%value,BadValueError:预期的键,获取[]首先需要保存一个用户实例,然后将其放置,您将分配该键而不是对象。ie event.participants=some_user.key,则其工作正常-因此,在上面的create_event代码中,您需要执行self.events.appendevent.keydb.ReferenceProperty支持的对象分配,但ndb.KeyProperty将只接受一个键。我添加了您的更改,文件现在看起来像这样,但错误仍然存在。get/insert和delete可以正常工作,但我不能毫无例外地接收所有用户。