'django update model doesn't affect auto_now timestamp

I've been trying to debug why the last_updated field in several of my models wasn't being updated when doing eg model.objects.filter(**lookups).update(**defaults) with eg:

class PaymentMethod(models.Model):
    MONTHLY_DIRECT_DEBIT = 'MDD'
    QUARTERLY_DIRECT_DEBIT = 'QDD'
    CASH_OR_CHEQUE = 'CAC'
    PAY_IN_ADVANCE = 'PYM'
    PAYMENT_CHOICES = (
        (MONTHLY_DIRECT_DEBIT, 'Monthly Direct Debit'),
        (QUARTERLY_DIRECT_DEBIT, 'Quarterly Direct Debit'),
        (CASH_OR_CHEQUE, 'Cash or Cheque'),
        (PAY_IN_ADVANCE, 'Pay Monthly in Advance'),
        
    )
    unique_id = models.CharField(max_length=3, choices=PAYMENT_CHOICES)
    last_updated = models.DateTimeField(auto_now=True)

    def __str__(self):

Here I am just trying to update a single entry and don't need to load the instance into memory. This seems to be a won't fix 'bug' explained in docshttps://code.djangoproject.com/ticket/15566 (for some reason I can't see it in the docs).

However, what is the best way to update a single row including the last_updated field (without needing to load into memory)?



Solution 1:[1]

I know the documented behavior is that .update() will ignore updating auto_now[_add] fields as is also confirmed by Yunti's answer. However, for those who wish to force the desired effect - for example, having an auto_now field updated as part of an .update() invocation, the following approach seems to work...

update(field1=val1, field2=val2,..., last_update=datetime.now())

Where last_update is a models.DateTime type field with (or without) auto_now=True. However, note that if you pass some other value to this field other than now() - the current timestamp that is, the ORM doesn't help in correcting this to the current timestamp (which is what the auto_now flag semantics imply). So, for example, in the following snippet, the last_update field does get overridden with the specified timestamp, irrespective of whether it's past, present or future...

    update(field1=val1, field2=val2,..., last_update=datetime.strptime('Jun 1 2005  1:33PM', '%b %d %Y %I:%M%p'))

So, if you wish to enforce the standard semantics of auto_now when making your calls to update(), ensure to correctly pass the current timestamp as the update value to these fields. You are doing it manually (due to a flaw/deficiency in the Django ORM implementation), but you are doing it correctly thus.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 JWL