Snowman
Snowman

Reputation: 32071

An appropriate key for a User entity in Google App Engine

I have a User entity in my Google App Engine model, and a user has a name, email, password, and some other stuff. Currently, I use the user's email as the key to the entity. Up until now, I hadn't considered what would happen if the user were to change his email.

The reason using email as the key was so convenient is that the client device always knows the users email, and rather than storing and keeping track of some separate user_id, it would be more convenient to just look up by email.

So what if the user does change their email? Is it a big deal after all - is the work to be done trivial? What are some better options for keys for a user?

Upvotes: 0

Views: 150

Answers (4)

dave_from_heuristics
dave_from_heuristics

Reputation: 123

Using the federated identity option on App Engine I've gone for an approach of having a primary_federated_identity as the key for each user. That way users can change email, handle, anything else but still be the same person.

Like @Tim Hoffman, as well as the primary_federated_identity I use a child entity but in my case it's a UserIdentity collection.

class User(db.Model):
    primary_federated_identity = db.StringProperty(required = True)
    handle = db.StringProperty(required = True)
    created = db.DateTimeProperty(required = True, auto_now_add = True)
    ...

class UserIdentity(db.Model):
    user = db.ReferenceProperty(User, collection_name = 'user_identities')
    user_federated_identity = db.StringProperty(required = True)
    user_federated_provider = db.StringProperty(required = True)
    ...

When I write a new user:

from google.appengine.api import users
from models.models import User
...
def some_function():
    key_name = users.federated_identity()
    my_site_user = User(key_name = key_name, primary_federated_identity=key_name, handle=handle)

And when I retrieve one:

key_name = user.federated_identity()
return User.get_by_key_name(key_name)

Upvotes: 2

Tim Hoffman
Tim Hoffman

Reputation: 12986

In a project I designed we have the login & hashed password plus other properties (enabled flag, password change flag etc) kept as a separate child entity of the user. The key of this entity was the login. This meant that the key (login) could be changed at any time, and we could remove/replace the child entity with out having to rekey things etc..... It did mean an ancestor query is required to get the user, but then this was cached (memcache etc) after the first retrieval.

This approach keeps all the login details out of the user, (we actually supported google logins as well as authtkt userid/passwd style logins, by changing the implementation of the child auth entity.)

Upvotes: 0

Shay Erlichmen
Shay Erlichmen

Reputation: 31928

if email == key then when a user wants to change his email you will need to create a new user entity.
Usually emails are not a good key for that reason, you can have a system that will replace all the old reference into new ones but that depends on how complicated is your system.

Upvotes: 0

Nicholas Albion
Nicholas Albion

Reputation: 3284

Use an int/Integer and GAE will assign a key value for you.

Upvotes: 1

Related Questions