使用端点-proto-datastore从KeyProperty获取引用实体

时间:2013-08-20 15:00:51

标签: google-app-engine google-cloud-endpoints endpoints-proto-datastore

我正在使用由Danny Hermes为Google App Engine创建的Endpoints-proto-datastore。

我的模型看起来像这样:

class Datum(EndpointsModel):
    year = ndb.IntegerProperty(required=True)
    value = ndb.FloatProperty(required=True)

class Variable(EndpointsModel):
    name = ndb.StringProperty(required=True)
    data = ndb.StructuredProperty(Datum, repeated=True)

class Indicator(EndpointsModel):
    name = ndb.StringProperty(required=True)
    variables = ndb.KeyProperty(kind=Variable, repeated=True)
    formula = ndb.StringProperty(required=True)

我的API是这样的:

@endpoints.api(name="SomeAPI", version="v1", description="someDescription")
class SomeAPI(remote.Service):
    @Indicator.query_method(query_fields=("limit", "pageToken"), 
                            name="indicator.list",
                            path="indicators")
    def list_indicators(self, query):
        return query

问题在于,当我提出请求时,我得到了

{
 "items": [
  {
   "name": "IndicatorName",
   "variables": [
    "agtkZXZ-bW9uaXRvcnITCxIIVmFyaWFibGUiBU1BVFJQDA",
    "agtkZXZ-bW9uaXRvcnISCxIIVmFyaWFibGUiBFBST1AM"
   ],
   "formula": "someFormula"
  }
 ]
}

但是获取变量键对我来说并不是真的有用,因为这会迫使客户端对指标实体上的变量做出另一个请求。我想获得变量内容,如下所示:

{
 "items": [
  {
   "name": "IndicatorName",
   "variables": [
     {
      "name": "some Variable",
      "data": [
       {
        "value": 230,
        "year": 2000,
       },
       {
        "value": 250,
        "year": 2005,
       }
      ]
     },
     {
      "name": "some other Variable",
      "data": [
       {
        "value": 230,
        "year": 2000,
       },
       {
        "value": 250,
        "year": 2005,
       },
       {
        "value": 260,
        "year": 2010,
       }
      ]
     }
   ],
   "formula": "someFormula"
  }
 ]
}

1 个答案:

答案 0 :(得分:2)

那你不想要KeyProperty。如果您想引用其他属性,请使用ndb.StructuredProperty

class Indicator(EndpointsModel):
    name = ndb.StringProperty(required=True)
    variables = ndb.StructuredProperty(Variable, repeated=True)

在像您这样的高级案例中,引用的对象可能会更改,但键不会更改,您可以使用EndpointsAliasProperty。有关某些参考点,请参阅docs以获取一些示例或某些StackOverflow问题Using endpoints-proto-datastore, how do you pass attributes to a method that are not contained in the EndpointsModelCloud Endpoints - Retrieving a single entity from datastore (by a property other than the helper methods provided by EndpointsModel)

更新:在添加了有关这些类的更多信息后,我发现了以下特殊需求:

对于这种特定情况,您希望将variables存储为variable_keys之类的其他名称,然后使用variables来检索键的值:

from endpoints_proto_datastore.ndb import EndpointsAliasProperty

class Indicator(EndpointsModel):
    name = ndb.StringProperty(required=True)
    variable_keys = ndb.KeyProperty(kind=Variable, repeated=True)
    formula = ndb.StringProperty(required=True)

然后作为Indicator上的实例方法定义你的getter(对于variables)没有关联的setter:

    @EndpointsAliasProperty(repeated=True, property_type=Variable.ProtoModel())
    def variables(self):
      return ndb.get_multi(self.variable_keys)

我还建议在_message_fields_schema类上设置Indicator,这样只有在你需要时调用此getter,因为get_multi是一个昂贵的RPC,如果你不使用它。然后,当您在查询中需要它时,可以将其包含在collection_fields

    @Indicator.query_method(query_fields=("limit", "pageToken"), 
                            collection_fields=("variables", ...),
                            name="indicator.list",
                            path="indicators")
    def list_indicators(self, query):
        return query

PS:查看PEP8 - Whitespace in Expressions and Statements; “当用于表示关键字参数或默认参数值时,请勿在=符号周围使用空格。”