Question

When using the endpoints-proto-datastore query_method on an EndpointsModel, is it possible to have an inequality filter passed as a query field?

For instance, say I have a model with a lastmodified field, and I want to query for all the records that have a lastmodified > date, where date is a value passed to the API by the client.

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

From the documentation I have seen, it seems like the query_fields is strictly an equality filter.

Was it helpful?

Solution

Yes, but you'll need to use an EndpointsAliasProperty with a name different than the lastmodified field. For example, you could do something like was done in the Picturesque app used as a sample at Google I/O 2013.

First, define your model

from google.appengine.ext import ndb

from endpoints_proto_datastore.ndb import EndpointsModel

class MyModel(EndpointsModel):

  attr1 = ndb.StringProperty()
  lastmodified = ndb.DateTimeProperty()

then create an alias property which will be used to update the query

from google.appengine.ext import endpoints

from endpoints_proto_datastore.ndb import EndpointsAliasProperty

  ...

  @EndpointsAliasProperty(name='modifiedSince', setter=ModifiedSinceSet)
  def ModifiedSince(self):
    raise endpoints.BadRequestException(
        'modifiedSince value should never be accessed.')

This property won't ever be accessed, but its setter is relevant to make the query sort on what we want, so we need to define ModifiedSinceSet (it needs to come before the variable is reference, as in the sample):

import datetime

from endpoints_proto_datastore import utils

  ...

  def ModifiedSinceSet(self, value):
    try:
      modified_since = utils.DatetimeValueFromString(value)
      if not isinstance(modified_since, datetime.datetime):
        raise TypeError('Not a datetime stamp.')
    except TypeError:
      raise endpoints.BadRequestException('Invalid timestamp for modifiedSince.')

    self._endpoints_query_info._filters.add(
        MyModel.lastmodified >= modified_since)

Here we convert the passed in value (from the request) to a datetime.datetime object and then use it to add a filter to self._endpoints_query_info._filters on the current EndpointsModel object.

This _endpoints_query_info is of course used in query_method to create the query that gets passed to your method.

Another alternative:

You could just parse the value and use introduce your own syntax. For example, accept strings like lastmodified>=TIMESTAMP and then parse the timestamp from the statement.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top