我对此有一个预感。但如果感觉我做错了。我想要做的是将db.StringProperty()作为唯一标识符。我有一个简单的db.Model,具有属性名称和文件。如果我添加另一个具有与db.Model中已有的相同“名称”的条目,我想更新它。
据我所知,我查了一下:
template = Templates.all().filter('name = ', name)
检查它是否已经是一个条目:
if template.count() > 0:
然后添加或更新它。但是从我读过的内容来看.count()的CPU使用率都很高。
是否可以将“name”属性设置为唯一,数据存储区会自动更新它还是另一种更好的方法来执行此操作?
..弗雷德里克
答案 0 :(得分:2)
您无法在App Engine数据存储区中创建唯一的属性。您可以做的是为模型指定一个密钥名称,保证其唯一性 - 有关详细信息,请参阅the docs。
答案 1 :(得分:2)
我遇到了同样的问题,并提出了以下答案作为最简单的答案:
class Car(db.Model):
name = db.StringProperty(required=True)
def __init__(self,*args, **kwargs):
super(Car, self).__init__(*args, **kwargs)
loadingAnExistingCar = ("key" in kwargs.keys() or "key_name" in kwargs.keys())
if not loadingAnExistingCar:
self.__makeSureTheCarsNameIsUnique(kwargs['name'])
def __makeSureTheCarsNameIsUnique(self, name):
existingCarWithTheSameName = Car.GetByName(name)
if existingCarWithTheSameName:
raise UniqueConstraintValidationException("Car should be unique by name")
@staticmethod
def GetByName(name):
return Car.all().filter("name", name).get()
重要的是我首先要检查我们是否先加载现有实体。
完整的解决方案:http://nicholaslemay.blogspot.com/2010/07/app-engine-unique-constraint.html
答案 2 :(得分:1)
您可以尝试获取实体并对其进行编辑,如果没有找到,则创建一个新实体:
template = Templates.gql('WHERE name = :1', name)
if template is None:
template = Templates()
# do your thing to set the entity's properties
template.put()
这样,它会在未找到时插入新条目,如果找到它,它将使用您所做的更改更新现有条目(请参阅文档here)。
答案 3 :(得分:1)
另一种解决方案是创建一个模型来存储唯一值,并使用Model.property_name.value
组合作为关键字来存储它。只有创建了该值,才能保存实际模型。这里用(代码)描述了这个解决方案:
http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/
答案 4 :(得分:0)
我同意尼克。但是,如果您确实想要根据属性检查模型/实体的存在,则get()方法很方便:
template = Templates.all().filter('name = ', name).get()
if template is None:
# doesn't exist
else:
# exists
答案 5 :(得分:0)
我写了一些代码来做到这一点。它的想法是非常容易使用。所以你可以这样做:
if register_property_value('User', 'username', 'sexy_bbw_vixen'):
return 'Successfully registered sexy_bbw_vixen as your username!'
else:
return 'The username sexy_bbw_vixen is already in use.'
这是代码。有很多评论,但实际上只有几行:
# This entity type is a registry. It doesn't hold any data, but
# each entity is keyed to an Entity_type-Property_name-Property-value
# this allows for a transaction to 'register' a property value. It returns
# 'False' if the property value is already in use, and thus cannot be used
# again. Or 'True' if the property value was not in use and was successfully
# 'registered'
class M_Property_Value_Register(db.Expando):
pass
# This is the transaction. It returns 'False' if the value is already
# in use, or 'True' if the property value was successfully registered.
def _register_property_value_txn(in_key_name):
entity = M_Property_Value_Register.get_by_key_name(in_key_name)
if entity is not None:
return False
entity = M_Property_Value_Register(key_name=in_key_name)
entity.put()
return True
# This is the function that is called by your code, it constructs a key value
# from your Model-Property-Property-value trio and then runs a transaction
# that attempts to register the new property value. It returns 'True' if the
# value was successfully registered. Or 'False' if the value was already in use.
def register_property_value(model_name, property_name, property_value):
key_name = model_name + '_' + property_name + '_' + property_value
return db.run_in_transaction(_register_property_value_txn, key_name )