Ответ 1
Нет встроенного ограничения для обеспечения уникальности значения. Вы можете сделать это, однако:
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
я знаю, какие из них не были уникальными.)
Как упоминалось в комментариях, эти подходы – по их первому, положите позже nature – выполните риск concurrency. Теоретически, объект может быть создан сразу после проверки существующего значения, а затем код после проверки будет выполняться, что приведет к дублированию значений. Чтобы предотвратить это, вам придется использовать транзакции: Транзакции - 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(...)
будет считать, что каждая пара ключей/значений должна быть уникальной для возврата успеха. Транзакция будет использовать единую группу объектов для каждого типа модели. Таким образом, транзакция является надежной для нескольких разных полей одновременно (только для одного поля это будет намного проще). Кроме того, даже если у вас есть поля с тем же именем в одной или нескольких моделях, они не будут конфликтовать с друг друга.