Question

I am trying to pass attributes into an API call that are not contained in my EndpointsModel. For example, say I have the following model:

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

Then assume I want to pass in attr2 as a parameter, but I don't want attr2 to be used as a filter nor do I want it to be stored in the model. I simply want to pass in some string, retrieve it inside of the method and use it to perform some business logic.

The documentation describes the query_fields parameter for specifying the fields you want to pass into the method, but these appear to be coupled to the attributes contained inside the model, therefore you cannot pass in attributes that are not specified in the model.

Likewise, the documentation states that you can pass in attributes via the path variable:

@MyModel.method(request_fields=('id',),
                path='mymodel/{id}', name='mymodel.get'
                http_method='GET')
def MyModelGet(self, my_model):
  # do something with id

But this requires you to change the URL, plus this appears to have the same constraint as query_fields (the attribute must exist in the model).

Was it helpful?

Solution

For just this use case, EndpointsAliasProperty was created. It acts much like @property does in Python in that you can specify a getter, setter and doc, but no deleter is specified in this context.

Since these properties will be sent over the wire and used with Google's API infrastructure, a type must be specified, so we can't just use @property. In addition, we need the typical property/field metadata such as repeated, required, etc.

Its use has been documented in one of the samples, but for your specific use case,

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

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

  def attr2_set(self, value):
    # Do some checks on the value, potentially raise
    # endpoints.BadRequestException if not a string
    self._attr2 = value

  @EndpointsAliasProperty(setter=attr2_set)
  def attr2(self):
    # Use getattr in case the value was never set
    return getattr(self, '_attr2', None)

Since no value for property_type was passed to EndpointsAliasProperty, the default of protorpc.messages.StringField is used. If instead you wanted an integer, you could've instead used:

@EndpointsAliasProperty(setter=attr2_set, property_type=messages.IntegerField)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top