Atomic transaction on django queryset.update(**kwargs)
<p>It seems <code>Django</code>'s <code>queryset.update</code> method execute under <code>transaction.atomic</code> context manager. When would I need to do that explicitly in my code during <code>update</code>? Or what will be the benefits doing it, or problems not doing it?</p>

<h2>Code</h2>

<pre><code>try:
    queryset = Model.objects.filter(a=1)
    if queryset.count():
        with transaction.atomic():
            queryset.update(a=2) # queryset will [] after this.
            for item in queryset: 
                item.emit_event('Updated')
except:
    logger.info('Exception')
</code></pre>

<p>My question is do I really need to have <code>transaction.atomic():</code> here? </p>

<p>Secondly, after <code>.update</code> my queryset gets empty because its a filtered queryset. how to retain the values in my case as I want to emit an event on the individual objects.</p>

<p><strong>First</strong></p>

<p>As <a href="https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic" rel="nofollow">docs</a> state</p>

<blockquote>
  <p>Atomicity is the defining property of database transactions. atomic allows us to create a block of code within which the atomicity on the database is guaranteed. If the block of code is successfully completed, the changes are committed to the database. If there is an exception, the changes are rolled back.</p>
</blockquote>

<p>In your example you would need <code>atomic</code> if <code>emit_event</code> is doing something and you want this update to be done only if all <code>emit_event</code> function calls and <code>queryset.update</code> are successfull. But if states of <code>emit_event</code> does not affect your business logic of update, <code>atomic</code> here would be redundant because as you said yourself <code>update</code> has internal <code>atomic</code>.</p>

<p><strong>Second</strong></p>

<p>Querysets are lazy. Which means evaluation of queryset will be done when you are iterating over it. So you need to do something like this. Answering latest comment</p>

<pre><code>try:
    queryset = Model.objects.filter(a=1)
    item_ids = list(queryset.values_list('id', flat=True)) # store ids for later
    if item_ids: # optimzing here instead of queryset.count() so there won't be hit to DB
        with transaction.atomic():
            queryset.update(a=2) # queryset will [] after this.
            for item in Model.objects.filter(id__in=item_ids):  # &lt;- new queryset which gets only updated objects
                item.emit_event('Updated')
except:
    logger.info('Exception')
</code></pre>

<p>See there we make new queryset when iterating over it to get updated items</p>

python django django-queryset