使用db.StringProperty()作为Google App Engine中的唯一标识符

时间:2010-02-10 09:55:12

标签: google-app-engine optimization google-cloud-datastore

我对此有一个预感。但如果感觉我做错了。我想要做的是将db.StringProperty()作为唯一标识符。我有一个简单的db.Model,具有属性名称和文件。如果我添加另一个具有与db.Model中已有的相同“名称”的条目,我想更新它。

据我所知,我查了一下:

template = Templates.all().filter('name = ', name)

检查它是否已经是一个条目:

if template.count() > 0:

然后添加或更新它。但是从我读过的内容来看.count()的CPU使用率都很高。

是否可以将“name”属性设置为唯一,数据存储区会自动更新它还是另一种更好的方法来执行此操作?

..弗雷德里克

6 个答案:

答案 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 )