1

I'm trying to make a method which will allow me to query an endpoint by a users email. Is there a better way to do so then what I'm doing below? One that only return one or zero records perhaps.

    @User.query_method(query_fields=('email',),
                       path='get_by_mail',
                       name='user.get_by_email')
    def get_by_email(self, query):
        return query
bossylobster
  • 9,993
  • 1
  • 42
  • 61
user672009
  • 4,379
  • 8
  • 44
  • 77

1 Answers1

2

I'm assuming User is some custom model that inherits from EndpointsModel. If not, this will fail. In other words, you've done something like this:

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

class User(EndpointsModel):
    email = ndb.StringProperty()
    ...

There are two primary approaches to solving this problem, you could either use the email as the key for the entity or roll your own query and try to fetch two entities to see if your result is unique and exists.

OPTION 1: Use email as the key

Instead of doing a full-on query, you could do a simple get.

from google.appengine.ext import endpoints

@endpoints.api(...)
class SomeClass(...):

    @User.method(request_fields=('email',),
                 path='get_by_mail/{email}',
                 http_method='GET', name='user.get_by_email')
    def get_by_email(self, user):
        if not user.from_datastore:
            raise endpoints.NotFoundException('User not found.')
        return user

by using the email as the datastore key for each entity, as is done in the custom alias properties sample. For example:

from endpoints_proto_datastore.ndb import EndpointsAliasProperty

class User(EndpointsModel):
    # remove email here, as it will be an alias property 
    ...

    def EmailSet(self, value):
        # Validate the value any way you like
        self.UpdateFromKey(ndb.Key(User, value))

    @EndpointsAliasProperty(setter=IdSet, required=True)
    def email(self):
        if self.key is not None: return self.key.string_id()

OPTION 2: Roll your own query

    @User.method(request_fields=('email',),
                 path='get_by_mail/{email}',
                 http_method='GET', name='user.get_by_email')
    def get_by_email(self, user):
        query = User.query(User.email == user.email)
        # We fetch 2 to make sure we have
        matched_users = query.fetch(2)
        if len(matched_users == 0):
            raise endpoints.NotFoundException('User not found.')
        elif len(matched_users == 2):
            raise endpoints.BadRequestException('User not unique.')
        else:
            return matched_users[0]
bossylobster
  • 9,993
  • 1
  • 42
  • 61
  • But later on I might want to find a user by his phone number. How would I go about that? – user672009 Mar 19 '13 at 21:17
  • Maybe I'm doing this entirely wrong. I want to make an android app which auths by the users google account and then basically have a endpoint model which has a reference to that user and a phone number... suggestions? – user672009 Mar 19 '13 at 22:17
  • Do you mind asking another question about best ways to identify users? It seems auth is being completely ignored here, but when storing user data, auth should be your first concern. – bossylobster Mar 19 '13 at 22:37
  • Not at all. I can assure you that your time wasn't wasted, I defiantly learned something from your answers. Thanks. – user672009 Mar 20 '13 at 00:00