我需要一些属性是独一无二的。我怎样才能做到这一点?
有没有类似的东西unique=True
?
我正在使用适用于 Python 的 Google App Engine。
我需要一些属性是独一无二的。我怎样才能做到这一点?
有没有类似的东西unique=True
?
我正在使用适用于 Python 的 Google App Engine。
谷歌提供了功能来做到这一点:
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。
没有用于确保值唯一的内置约束。但是,您可以这样做:
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
值,则您知道存在重复值(并检查哪些值 not 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(...)
将假定每个键/值对都必须是唯一的才能返回成功。该事务将为每个模型类型使用一个实体组。这样,事务同时对几个不同的字段是可靠的(对于一个字段,这会简单得多。)此外,即使您在一个或多个模型中有同名的字段,它们也不会与彼此。