当前位置:  开发笔记 > 编程语言 > 正文

如何在Google App Engine中为模型定义唯一属性?

如何解决《如何在GoogleAppEngine中为模型定义唯一属性?》经验,为你挑选了2个好方法。

我需要一些独特的属性.我怎样才能做到这一点?

有类似的东西unique=True吗?

我正在使用Google App Engine for Python.



1> 小智..:

谷歌提供了这样做的功能:

http://code.google.com/appengine/docs/python/datastore/modelclass.html#Model_get_or_insert

Model.get_or_insert(key_name, **kwds)

尝试使用给定的密钥名称获取模型类型的实体.如果存在,get_or_insert()只返回它.如果它不存在,则创建,存储和返回具有kwds中给定种类,名称和参数的新实体.

get和后续(可能)put被包装在事务中以确保原子性.这意味着get_or_insert()将永远不会覆盖现有实体,并且当且仅当不存在具有给定种类和名称的实体时才会插入新实体.

换句话说,get_or_insert()等效于此Python代码:

def txn():
  entity = MyModel.get_by_key_name(key_name, parent=kwds.get('parent'))
  if entity is None:
    entity = MyModel(key_name=key_name, **kwds)
    entity.put()
  return entity
return db.run_in_transaction(txn)

参数:

key_name实体键的名称**kwds如果不存在具有指定键名的实例,则传递给模型类构造函数的关键字参数.如果所需实体具有父级,则必需父参数.

注意:get_or_insert()不接受RPC对象.

该方法返回表示所请求实体的模型类的实例,无论该实体是存在还是由该方法创建.与所有数据存储区操作一样,如果无法完成事务,此方法可能会引发TransactionFailedError.



2> Blixt..:

没有内置约束来确保值是唯一的.但是你可以这样做:

query = MyModel.all(keys_only=True).filter('unique_property', value_to_be_used)
entity = query.get()
if entity:
    raise Exception('unique_property must have a unique value!')

我使用keys_only=True它是因为它不会通过获取实体的数据来略微提高性能.

一种更有效的方法是使用一个单独的模型,该模型没有其键名由属性名+值组成的字段.然后你可以get_by_key_name用来获取这些复合键名中的一个或多个,如果你得到一个或多个not- None值,你知道有重复的值(并检查哪些值不是None,你会知道哪些不是唯一的.)


正如评论中提到的那样,这些方法 - 通过先获得,后来的自然 - 运行风险并发问题.从理论上讲,可以在检查现有值之后创建实体,然后检查后的代码仍将执行,从而导致重复值.为防止这种情况,您必须使用交易:交易 - Google App Engine


如果您希望检查所有具有事务的实体的唯一性,则必须使用第一种方法将所有实体放在同一组中,这样效率非常低.对于事务,请使用第二种方法,如下所示:

class UniqueConstraint(db.Model):
    @classmethod
    def check(cls, model, **values):
        # Create a pseudo-key for use as an entity group.
        parent = db.Key.from_path(model.kind(), 'unique-values')

        # Build a list of key names to test.
        key_names = []
        for key in values:
            key_names.append('%s:%s' % (key, values[key]))

        def txn():
            result = cls.get_by_key_name(key_names, parent)
            for test in result:
                if test: return False
            for key_name in key_names:
                uc = cls(key_name=key_name, parent=parent)
                uc.put()
            return True

        return db.run_in_transaction(txn)

UniqueConstraint.check(...)将假设每个键/值对必须是唯一的才能返回成功.该事务将为每种模型使用单个实体组.这样,事务对于几个不同的字段同时是可靠的(对于一个字段,这将更加简单.)此外,即使您在一个或多个模型中具有相同名称的字段,它们也不会与彼此.

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有