Google App Engine模型的自定义键(Python) [英] Custom keys for Google App Engine models (Python)

查看:80
本文介绍了Google App Engine模型的自定义键(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
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $' '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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆