Claves personalizadas para los modelos de Google App Engine (Python)

En primer lugar, soy relativamente nuevo en Google App Engine, así que probablemente estoy haciendo algo tonto.

Digamos que tengo un modelo Foo:

class Foo(db.Model): name = db.StringProperty() 

Quiero usar el name como una clave única para cada objeto Foo . ¿Cómo se hace esto?

Cuando quiero obtener un objeto Foo específico, actualmente busco en el almacén de datos todos los objetos Foo con el nombre único de destino, pero las consultas son lentas (además, es un dolor asegurarse de que ese name sea ​​único cuando se crea cada nuevo Foo ).

¡Tiene que haber una mejor manera de hacer esto!

Gracias.

He usado el código de abajo en un proyecto antes. Funcionará siempre y cuando el campo en el que está basando su nombre de clave sea obligatorio.

 class NamedModel(db.Model): """A Model subclass for entities which automatically generate their own key names on creation. See documentation for _generate_key function for requirements.""" def __init__(self, *args, **kwargs): kwargs['key_name'] = _generate_key(self, kwargs) super(NamedModel, self).__init__(*args, **kwargs) def _generate_key(entity, kwargs): """Generates a key name for the given entity, which was constructed with the given keyword args. The entity must have a KEY_NAME property, which can either be a string or a callable. If KEY_NAME is a string, the keyword args are interpolated into it. If it's a callable, it is called, with the keyword args passed to it as a single dict.""" # Make sure the class has its KEY_NAME property set if not hasattr(entity, 'KEY_NAME'): raise RuntimeError, '%s entity missing KEY_NAME property' % ( entity.entity_type()) # Make a copy of the kwargs dict, so any modifications down the line don't # hurt anything kwargs = dict(kwargs) # The KEY_NAME must either be a callable or a string. If it's a callable, # we call it with the given keyword args. if callable(entity.KEY_NAME): return entity.KEY_NAME(kwargs) # If it's a string, we just interpolate the keyword args into the string, # ensuring that this results in a different string. elif isinstance(entity.KEY_NAME, basestring): # Try to create the key name, catching any key errors arising from the # string interpolation try: key_name = entity.KEY_NAME % kwargs except KeyError: raise RuntimeError, 'Missing keys required by %s entity\'s KEY_NAME '\ 'property (got %r)' % (entity.entity_type(), kwargs) # Make sure the generated key name is actually different from the # template if key_name == entity.KEY_NAME: raise RuntimeError, 'Key name generated for %s entity is same as '\ 'KEY_NAME template' % entity.entity_type() return key_name # Otherwise, the KEY_NAME is invalid else: raise TypeError, 'KEY_NAME of %s must be a string or callable' % ( entity.entity_type()) 

Entonces podrías modificar tu modelo de ejemplo así:

 class Foo(NamedModel): KEY_NAME = '%(name)s' name = db.StringProperty() 

Por supuesto, esto podría simplificarse dramáticamente en su caso, cambiando la primera línea del método __init__ a algo como:

 kwargs['key_name'] = kwargs['name'] 

Aquí hay una discusión bastante completa sobre la ausencia de equidad con el almacén de datos de AppEngine: ¿Cómo defino una propiedad única para un modelo en el motor de aplicaciones de Google?