2016-06-19 3 views
0

У меня есть метод сохранения из класса util в моем приложении для библиотеки. В самостоятельной определено utils.py:Django Atomic Transactions для связанных с методом транзакций

def update_book_count(key): 
    key_to_update = BookConfig.objects.get(key=key) 
    """ 
    returns {'key': 'Chemistry-700', 'count': 15} 
    """ 
    key_to_update.count = key_to_update.count + 1 
    key_to_update.save() 

Рассмотрим этот код в forms.py:

class AddBookForm(forms.Form): 
    #some fields 

    def save(self): 
     title = self.cleaned_data.get('title') 
     category = self.cleaned_data.get('category') #Chemistry 

     try: 
      with transaction.atomic(): 
       book = Book(title=title, category=category) 
       book.save(force_insert=True, force_update=False) 
       update_book_count(category) 
       #Say just for this case, I find reservations for this title 
       loan = Loan.objects.filter(
       title=title,status="PENDING_BOOK_PURCHASE") 
       loan.update(status="PENDING_MEMBER_COLLECTION") 
     except IntegrityError: 
      print("Atomic Txn Error") 

Мой вопрос заключается в следующем: atomic() Распространяется ли на операции базы данных в методе update_book_count? В частности:

  1. Если метод update_book_count терпит неудачу, делает book.save() сделки получить откат тоже?
  2. Если метод loan.update() терпит неудачу, возвращается ли возврат update_book_count?

ответ

1

Во-первых, чтобы ответить на ваши вопросы:

  1. Если исключение пузырьков и из with заявления (который смотрит на ваш код будет), то да, то сделка будет скататься назад.

  2. Да, когда транзакция откатывается назад, все, что произошло до сих пор, будет отменено.

Кстати, вы должны использовать сигналы для автоматического обновления таких подсчета полей, так что вы никогда не придется беспокоиться о забывая вызвать метод вручную (и, как и прежде, это будет предметом сделки, если выполняются внутри одного). И вы получаете дополнительное преимущество от работы, когда объекты удаляются.

from django.db.models.signals import post_save, post_delete 
from django.dispatch import receiver 
from django.db import transaction 

@receiver(post_save, sender=Book) 
@receiver(post_delete, sender=Book) 
@transaction.atomic 
def _update_count(sender, instance, using, **kwargs): 
    # get total number of books with this category 
    count = Book.objects.filter(category=instance.category).count() 

    # update the denormalized data 
    BookConfig.objects.filter(key=instance.category).update(count=count) 

Django signal documentation.