Use a db.StringProperty() as unique identifier in Google App Engine

ε祈祈猫儿з 提交于 2019-12-22 18:32:23

问题


I just have a hunch about this. But if feels like I'm doing it the wrong way. What I want to do is to have a db.StringProperty() as a unique identifier. I have a simple db.Model, with property name and file. If I add another entry with the same "name" as one already in the db.Model I want to update this.

As of know I look it up with:

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

Check if it's one entry already:

if template.count() > 0:

Then add it or update it. But from what I've read .count() is every expensive in CPU usage.

Is there away to set the "name" property to be unique and the datastore will automatic update it or another better way to do this?

..fredrik


回答1:


You can't make a property unique in the App Engine datastore. What you can do instead is to specify a key name for your model, which is guaranteed to be unique - see the docs for details.




回答2:


I was having the same problem and came up with the following answer as the simplest one :

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()

It's important to not that I first check if we are loading an existing entity first.

For the complete solution : http://nicholaslemay.blogspot.com/2010/07/app-engine-unique-constraint.html




回答3:


You can just try to get your entity and edit it, and if not found create a new one:

template = Templates.gql('WHERE name = :1', name)
if template is None:
  template = Templates()

# do your thing to set the entity's properties

template.put()

That way it will insert a new entry when it wasn't found, and if it was found it will update the existing entry with the changes you made (see documentation here).




回答4:


An alternative solution is to create a model to store the unique values, and store it transationally using a combination of Model.property_name.value as key. Only if that value is created you save your actual model. This solution is described (with code) here:

http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/




回答5:


I agree with Nick. But, if you do ever want to check for model/entity existence based on a property, the get() method is handy:

template = Templates.all().filter('name = ', name).get()
if template is None:
  # doesn't exist
else:
  # exists



回答6:


I wrote some code to do this. The idea for it is to be pretty easy to use. So you can do this:

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 is the code. There are a lot of comments, but its actually only a few lines:

# 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 )


来源:https://stackoverflow.com/questions/2235840/use-a-db-stringproperty-as-unique-identifier-in-google-app-engine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!