2014-09-04 2 views
1

Я хочу создать и объект, сохранить его в БД, а затем проверить, есть ли еще одна строка в БД с тем же token с execution_time = 0. Если есть, я хочу удалить созданный объект, а затем перезапустить процесс.Должен ли я совершать транзакции в Django 1.6?

transfer = Transfer(token = generateToken(size=9)) 
transfer.save() 
while (len(Transfer.objects.filter(token=transfer.token, execution_time=0))!=1): 
    transfer.delete() 
    transfer = Transfer(token = generateToken(size=9)) 
    transfer.save() 

Должен ли я совершить транзакцию между каждым циклом? Например, звоните commit() в конце каждого цикла?

while (len(Transfer.objects.filter(token=transfer.token, execution_time=0))!=1): 
    transfer.delete() 
    transfer = Transfer(token = generateToken(size=9)) 
    transfer.save() 
    commit() 

@transaction.commit_manually 
def commit(): 
    transaction.commit() 
+0

Возможно, было бы полезно добавить atomic = True в настройки вашего django. это превращает каждое взаимодействие с базами данных в транзакцию./ – agconti

ответ

0

Из того, что вы описали, я не думаю, что вам нужно использовать транзакции. Вы в основном воссоздаете транзакционный откат вручную с помощью своего кода.

Я думаю, что лучшим способом справиться с этим было бы ограничение базы данных, обеспечивающее эту проблему. Это так, что token и execution_time должны быть уникальными вместе? В этом случае вы можете определить ограничение в Django с помощью unique_together. Если ограничение состоит в том, что token должно быть уникальным, когда execution_time равно 0, некоторые базы данных также позволят вам определить ограничение, подобное этому.

Если ограничение было в базе данных, вы могли бы просто сделать get_or_create() в цикле до Transfer было created.

Если вы не можете определить ограничение в базе данных по какой-либо причине, то я думаю, что ваша версия будет работать. (Одно усовершенствование было бы использовать .count() вместо len.)

0

Я хочу создать и объект, сохранить его в БД, то проверьте, есть ли другой ряд на БД с тем же самым с Execution_time = 0 , Если есть , я хочу удалить созданный объект, а затем перезапустить процесс .

Есть несколько способов, вы можете подойти к этому, в зависимости от того, что ваша конечная цель:

  1. Вы хотите, что ни одна другая запись не будет в то время как вы пишете ваши (чтобы предотвратить дубликаты?) Если это так, вам нужно получить блокировку на своем столе, и для этого вам необходимо выполнить атомную транзакцию, с @transaction.atomic (новый в версии 1.6)

  2. Если вы хотите убедиться, что не созданы дубликаты записей учитывая комбинацию полей, вам необходимо обеспечить это в базе данных с unique_together

Я считаю, что объединение двух вышеуказанных будет решить вашу проблему; однако, если вы хотите использовать более грубую силу; вы можете переопределить метод save() для своего объекта, а затем поднять соответствующее исключение, когда запись пытается создать или обновить запись, которая нарушает ваши ограничения.

На ваш взгляд, вы поймете это исключение и затем предпримите соответствующие действия.

+0

Что касается 1, обычно не считается, что начало транзакции блокирует таблицу (или ее эквивалент).Это будет зависеть от базы данных, ее настройки и уровня изоляции транзакции. Поэтому вы не можете предположить, что работа внутри транзакции будет предотвращать одновременные вставки. –

Смежные вопросы