Google App Engine模型的自定义键(Python) [英] Custom keys for Google App Engine models (Python)
问题描述
首先,我对Google App Engine比较陌生,所以我可能会做一些愚蠢的事情。
假设我有一个Foo模型:
class Foo(db.Model):
name = db.StringProperty()
我想用 name
作为每个 Foo
对象。这是如何完成的?
当我想要获取特定的 Foo
对象时,我当前正在查询数据存储 Foo
具有目标唯一名称的对象,但查询很慢(加上确保 name
是唯一的每个新的 Foo
都会被创建)。
有一个更好的方法可以做到这一点!
谢谢。
我以前在项目中使用过下面的代码。只要您需要使用您的密钥名称的字段,它就会工作。
class NamedModel(db。模型):
实体的模型子类,它在创建时自动生成自己的关键
名称。请参阅关于
要求的_generate_key函数的文档。
def __init __(self,* args,** kwargs):
kwargs ['key_name'] = _generate_key(self,kwargs)
super(NamedModel,self).__ init __(* args,** kwargs)
$ b $ def _generate_key(entity,kwargs):
为给定实体生成一个键名,该实体由
构成,给定关键字args 。实体必须有一个KEY_NAME属性,
既可以是字符串也可以是可调用的
如果KEY_NAME是一个字符串,则将关键字args插入到该字符串中;如果
它是一个可调用的函数,它被调用,关键字args作为
单个字典传递给它。
#确保如果不是hasattr(实体,'KEY_NAME'),则它的KEY_NAME属性设置
:
raise RuntimeError,'%s实体缺少KEY_NAME属性'%(
entity.entity_type())
#制作kwargs字典的副本,因此任何修改都不会造成
#伤害任何内容
kwargs = dict(kwargs)
# KEY_NAME必须是可调用的字符串或字符串。如果它是可调用的,
#我们用给定的关键字args调用它。
如果可调用(entity.KEY_NAME):
返回entity.KEY_NAME(kwargs)
#如果它是一个字符串,我们只需将关键字args插入字符串
#确保这会导致不同的字符串。
elif isinstance(entity.KEY_NAME,basestring):
#尝试创建密钥名称,捕获由
#字符串插值引起的任何重要错误
try:
key_name = entity.KEY_NAME%kwargs
,除了KeyError:
引发RuntimeError,'缺少%s实体\的KEY_NAME所需的键'\ $ b $'属性(got%r)'% (entity.entity_type(),kwargs)
#确保生成的键名实际上与
#模板不同
if key_name == entity.KEY_NAME:
'引发RuntimeError,'为%s实体生成的键名与''相同'\ $ b $'KEY_NAME模板'%entity.entity_type()
返回键名
#否则,KEY_NAME无效
else:
引发TypeError,'%s的KEY_NAME必须是字符串或可调用'%(
entity.entity_type())
然后,您可以修改您的示例模型,如下所示:
class Foo(NamedModel):
KEY_NAME ='%(name)s'
name = db.StringProperty()
当然,在你的情况下,这可以大大简化,改变 NamedModel $ c的第一行
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' 'key_name'] = kwargs ['name']
First off, I'm relatively new to Google App Engine, so I'm probably doing something silly.
Say I've got a model Foo:
class Foo(db.Model):
name = db.StringProperty()
I want to use name
as a unique key for every Foo
object. How is this done?
When I want to get a specific Foo
object, I currently query the datastore for all Foo
objects with the target unique name, but queries are slow (plus it's a pain to ensure that name
is unique when each new Foo
is created).
There's got to be a better way to do this!
Thanks.
I've used the code below in a project before. It will work as long as the field on which you're basing your key name on is required.
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())
You could then modify your example model like so:
class Foo(NamedModel):
KEY_NAME = '%(name)s'
name = db.StringProperty()
Of course, this could be dramatically simplified in your case, changing the first line of the NamedModel
's __init__
method to something like:
kwargs['key_name'] = kwargs['name']
这篇关于Google App Engine模型的自定义键(Python)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!