gpt4 book ai didi

google-cloud-endpoints - Cloud Endpoints - 从数据存储中检索单个实体(通过 EndpointsModel 提供的辅助方法以外的属性)

转载 作者:行者123 更新时间:2023-12-03 21:26:51 28 4
gpt4 key购买 nike

这个问题完全来自我在这里问过(并得到回答)的相关问题:Error when trying to retrieve a single entity

据我了解,要使用已提供的辅助方法以外的属性(例如 'id' )从数据存储中检索单个实体需要将简单的数据属性转换为 EndpointsAliasProperty ?如果是,我将如何去做?还是我们只能使用 'id' (由 EndpointsModel 提供的辅助方法)而不能使用我们定义的任何属性(在本例中为 'title' )?

最佳答案

自定义 EndpointsAliasProperty 与您定义的数据属性之一之间的区别在于它们的使用方式。它们都用于创建 protorpc 消息,然后该消息将转换为 EndpointsModel,其中包含您的自定义数据。 这个 是魔法发生的地方。

将其分解为以下步骤:

1. 你指定你的数据

from google.appengine.ext import ndb
from endpoints_proto_datastore.ndb import EndpointsModel

class MyModel(EndpointsModel):
my_attr = ndb.StringProperty()

2. 你为你的方法选择你的领域
class MyApi(...):

@MyModel.method(request_fields=('id', 'my_attr'), ...)
def my_method(self, my_model_entity):
...

3. protorpc 消息类是从您的字段中定义的
>>> request_message_class = MyModel.ProtoModel(fields=('id', 'my_attr'))
>>> request_message_class
<class '.MyModelProto_id_my_attr'>
>>> for field in request_message_class.all_fields():
... print field.name, ':', field.variant
...
id : INT64
my_attr : STRING

这种情况发生在 every time 请求由 @MyModel.method 修饰的方法处理。

4. 一个请求进入你的应用程序并创建一条消息

使用 protorpc 消息类,从 JSON 解析消息实例,该 JSON 传递到您的端点 SPI(由 endpoints.api_server 创建)。

当请求进入您的 protorpc.remote.Service 时,它​​是 decoded :
>>> from protorpc import remote
>>> protocols = remote.Protocols.get_default()
>>> json_protocol = protocols.lookup_by_content_type('application/json')
>>> request_message = json_protocol.decode_message(
... request_message_class,
... '{"id": 123, "my_attr": "some-string"}'
... )
>>> request_message
<MyModelProto_id_my_attr
id: 123
my_attr: u'some-string'>

5. protorpc 消息是 cast into a datastore model
entity = MyModel.FromMessage(request_message)

这个 是您真正关心的步骤。 FromMessage 类方法(也作为 EndpointsModel 的一部分提供)循环遍历所有字段
for field in sorted(request_message_class.all_fields(),
key=lambda field: field.number):

并且对于设置了值的每个字段,将值转换为要添加到实体的内容,并根据属性是否为 EndpointsAliasProperty 进行分隔:
    if isinstance(value_property, EndpointsAliasProperty):
alias_args.append((local_name, to_add))
else:
entity_kwargs[local_name] = to_add

完成这个循环后,我们有一个所有键、值对的有序列表 alias_args 和从消息中解析出的数据属性的字典 entity_kwargs

使用这些,首先是一个简单的实体 is created
entity = MyModel(**entity_kwargs)

然后按 的顺序设置每个别名属性值 :
for name, value in alias_args:
setattr(entity, name, value)

扩展行为发生在 setattr(entity, name, value) 中。由于 EndpointsAliasProperty property 的子类,它是一个描述符并且它有一个 setter 可以执行一些自定义行为 除了 简单地设置一个值。

例如, id 属性是 defined with :
@EndpointsAliasProperty(setter=IdSet, property_type=messages.IntegerField)
def id(self):

setter 执行的操作不仅仅是设置数据:
def IdSet(self, value):
self.UpdateFromKey(ndb.Key(self.__class__, value))

此特定方法尝试使用 id 检索存储在数据存储中的实体,并修补数据存储中未包含在从请求中解析的实体中的任何值。

如果您想对 my_attr 之类的字段执行此操作,则需要构建一个自定义查询,该查询可以检索具有该唯一 my_attr 值的项目(如果不完全存在这样的实体,则失败)。

这是有问题的,您最好使用唯一字段,例如用于在数据存储中存储实体的键或 ID。

keys with ancestors 示例提供了一个很好的示例来创建您自己的自定义属性。

如果您 真的 坚持使用 my_attr 来检索实体,您可以使用不同的属性名称(因为 my_attr 已用于数据属性),例如 fromMyAttr :
class MyModel(EndpointsModel):
def MyAttrSet(self, value):
...
@EndpointsAliasProperty(setter=MyAttrSet)
def fromMyAttr(self):
...

在这里, MyAttrSet 实例方法将形成查询:
    def MyAttrSet(self, value):
query = MyModel.query(MyModel.my_attr == value)
results = query.fetch(2)

拒绝对 my_attr 不唯一的结果:
        if len(results) == 0:
raise endpoints.NotFoundException('Not found.')
if len(results) == 2:
raise endpoints.BadRequestException('Colliding results.')

如果我们确实找到了唯一的实体,则复制已存储实体的值:
        matching_entity = results[0]
self._CopyFromEntity(matching_entity)
self._from_datastore = True

关于google-cloud-endpoints - Cloud Endpoints - 从数据存储中检索单个实体(通过 EndpointsModel 提供的辅助方法以外的属性),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16755372/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com