Google应用程序引擎模型的自定义键(Python)
首先,我对谷歌应用程序引擎还比较陌生,所以我可能在做一些愚蠢的事情 假设我有一个Foo模型:Google应用程序引擎模型的自定义键(Python),python,google-app-engine,google-cloud-datastore,primary-key,Python,Google App Engine,Google Cloud Datastore,Primary Key,首先,我对谷歌应用程序引擎还比较陌生,所以我可能在做一些愚蠢的事情 假设我有一个Foo模型: class Foo(db.Model): name = db.StringProperty() 我想使用name作为每个Foo对象的唯一键。这是怎么做到的 当我想要获取一个特定的Foo对象时,我当前会在数据存储中查询具有目标唯一名称的所有Foo对象,但查询速度很慢(另外,在创建每个新的Foo时,确保name是唯一的也是一件痛苦的事情) 一定有更好的办法 谢谢。以下是关于AppEngine数据存储
class Foo(db.Model):
name = db.StringProperty()
我想使用name
作为每个Foo
对象的唯一键。这是怎么做到的
当我想要获取一个特定的Foo
对象时,我当前会在数据存储中查询具有目标唯一名称的所有Foo
对象,但查询速度很慢(另外,在创建每个新的Foo
时,确保name
是唯一的也是一件痛苦的事情)
一定有更好的办法
谢谢。以下是关于AppEngine数据存储的不合格性的详细讨论:
我以前在一个项目中使用过下面的代码。只要您的密钥名所基于的字段是必需的,它就可以工作
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())
然后,您可以修改示例模型,如下所示:
class Foo(NamedModel):
KEY_NAME = '%(name)s'
name = db.StringProperty()
当然,在您的例子中,这可以大大简化,将NamedModel
的\uuuu init\uuuu
方法的第一行更改为如下内容:
kwargs['key_name'] = kwargs['name']
啊,这看起来很酷,但有点过分了。不管怎样,它仍然引导我走上了正确的道路,发现了我所缺少的东西:关于key_name的知识!这是一切的关键:-)哈哈哈,我很高兴我至少为你指出了正确的方向。如果正在创建的模型实例已经有了一个键,例如在查询结果集中,会发生什么。我的理解是,除了第一次在数据存储中创建实体时被调用外,该实体的init函数还将在任何时候创建该类的实例时被调用。