The newest App Engine SDK (1.2.1) has an API call to compute an ID for a user account based on his email address. (The ID remains the same even if the user changes his address later.) See this question about unique, opaque user IDs for information. However, I have a problem with this API call.
user_id()
works for logged-in users (i.e. from users.get_current_user)
, but it returns None
for objects created by the users.User()
constructor.** What gives?
For example, using the excellent App Engine Console, this code does not work.
>>> import google.appengine.api.users
>>> me = google.appengine.api.users.get_current_user()
>>> me
users.User(email='[email protected]',_user_id='105261964646342707921')
>>> me.user_id()
'105261964646342707921'
>>> somebody = google.appengine.api.users.User('[email protected]')
>>> somebody
users.User(email='[email protected]')
>>>somebody.user_id()
>>> type(somebody.user_id())
<type 'NoneType'>
I want a simple way to convert an email address to a user ID. How can I coerce this ID from Google ahead of time; or if it's not possible, why not?
Thanks to Nick Johnson for his answer. Here is his solution in action:
>>> from google.appengine.ext import db
>>> from google.appengine.api import users
>>> class User(db.Model):
... user = db.UserProperty(required=True)
...
>>> def email_to_userid(address):
... """Return a stable user_id string based on an email address, or None if
... the address is not a valid/existing google account."""
... u = users.User(address)
... key = User(user=u).put()
... obj = User.get(key)
... return obj.user.user_id()
>>> email_to_userid('[email protected]')
u'105261964646342707921'
>>> email_to_userid('this@is-an-invalid-email-address')
>>> email_to_userid('this@is-an-invalid-email-address') is None
True
The current workaround is to create a User object, store it to the datastore, and fetch it again. If the email corresponds to a valid Google account, the User object in the returned entity will have its user_id field populated.
To make the proposed solution work with NDB, just add use_cache=False, use_memcache=False to the get method. That is:
obj = key.get(use_cache=False, use_memcache=False)
This guarantees getting the entity from the Datastore with the user_id param populated (only if this is a valid Google account).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With