[Django] #22981: Fields with auto_now=True are not updated if the field name is not present in update_fields list passed into Model.save

123 views
Skip to first unread message

Django

unread,
Jul 8, 2014, 10:44:10 PM7/8/14
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
----------------------------------------------+--------------------
Reporter: jscn | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: 1.6
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
Passing `update_fields` into a model's `save` method fails to update
fields on the model which have `auto_now=True` specified but which are not
included in the `update_fields` parameter.

I think it's a fairly common use case to have a base model which records
when the instance was last updated:

{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python
class MyModel(models.Model):
updated_at = models.DateTimeField(auto_now=True)
}}}
}}}

But, now I have to remember to always include `updated_at` in my list of
`updated_fields`:

{{{
#!div style="font-size: 80%"
Code highlighting:
{{{#!python

In [2]: m = MyModel.objects.latest('updated_at')

In [3]: m.updated_at
Out[3]: datetime.datetime(2014, 7, 9, 1, 12, 12, 850847, tzinfo=<UTC>)

In [4]: m.save()

In [5]: m.updated_at
Out[5]: datetime.datetime(2014, 7, 9, 1, 12, 12, 850847, tzinfo=<UTC>)

In [6]: m.save(update_fields=['updated_at'])

In [7]: m.updated_at
Out[7]: datetime.datetime(2014, 7, 9, 2, 21, 48, 412890, tzinfo=<UTC>)

}}}
}}}


So if I have an instance of a subclass of this model and only want to
update some unrelated field on that subclass, then I have to a) know that
it inherits from `MyModel` and b) know that `MyModel` has a field with
`auto_now=True` and what that field's name is and c) remember to include
that in the `updated_fields` list whenever I use it. This seems like a lot
of overhead!

Ticket #15566 addresses a similar problem (but covers the case of using
`Manager.update`, rather than `Model.save`) and was determined to be a
documentation issue largely because `Manager.update` is for updating
multiple rows with a single SQL statement whereas `auto_now` and friends
involve per-row calculations.

Since `Model.save` is only updating a single row, that argument doesn't
hold in this case, so I'm inclined to think this is a bug rather than a
documentation issue.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jul 9, 2014, 2:47:56 PM7/9/14
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------

Reporter: jscn | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.6
(models, ORM) | Resolution:
Severity: Normal | Triage Stage:
Keywords: | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timo):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

What you consider a bug, others may consider a feature, e.g. using
`update_fields` to bypass updating fields with `auto_now`. In fact, I
wouldn't expect `auto_now` fields to be updated if not present in
`update_fields`.

I tend to think we won't make the change due to backwards compatibility,
but I will leave open for a second opinion. We can at least document the
caveat.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:1>

Django

unread,
Jul 29, 2014, 7:28:15 AM7/29/14
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: jscn | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.6
(models, ORM) | Resolution: wontfix

Severity: Normal | Triage Stage:
Keywords: | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timo):

* status: new => closed
* resolution: => wontfix


Comment:

From #22995 comment 11:

"I think we should at least deprecate (`auto_now(_add)`) because the use
case is very obvious but `auto_now(_add)` don't implement it — and maybe
can't!
Creation and modification timestamps are expected to be set
automatically, regardless of how you access the row. Rails does this well
at the database level."

If you are looking for the behavior you describe, try adding a database
default.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:2>

Django

unread,
Apr 22, 2015, 11:46:18 PM4/22/15
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: jscn | Owner: nobody

Type: Bug | Status: closed
Component: Database layer | Version: 1.6
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by npinchot):

I also would like the ability for `auto_now` fields to always be updated
even if `update_fields` is used and they are not passed in. I agree that
the current behavior of the way `update_fields` interacts with `auto_now`
should stay as is.

Would you accept a patch which implements a new `auto_now_always`
parameter which would provide the requested behavior of automatically
pushing these fields into `update_fields` if not passed in?

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:3>

Django

unread,
Apr 23, 2015, 7:26:27 AM4/23/15
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: jscn | Owner: nobody

Type: Bug | Status: closed
Component: Database layer | Version: 1.6
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by timgraham):

Is there a problem with the suggestion of using a database default for
your use case? I don't think more "auto" options are desired considering
there has been some though to deprecate them (#22995).

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:4>

Django

unread,
May 13, 2015, 11:22:52 PM5/13/15
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: jscn | Owner: nobody

Type: Bug | Status: closed
Component: Database layer | Version: 1.6
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by npinchot):

Replying to [comment:4 timgraham]:


> Is there a problem with the suggestion of using a database default for
your use case? I don't think more "auto" options are desired considering
there has been some though to deprecate them (#22995).

Forgive my ignorance if I'm wrong, but my understanding is a database
default won't mimic 'auto_now' behavior since it would only default on
INSERT and won't change the value on UPDATE. It seems I would need a
trigger to mimic the 'auto_now' behavior. I know MySQL also has a
timestamp column type, but my understanding is this isn't the same as a
datetime and won't work the same.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:5>

Django

unread,
Aug 3, 2017, 1:09:04 PM8/3/17
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: Josh Crompton | Owner: nobody

Type: Bug | Status: closed
Component: Database layer | Version: 1.6
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Dylan Young):

Any status on this?

Some thoughts:

If auto_now_add, as you're suggesting, should be implemented as a database
default, then why hasn't Django done this? Since, as you say, this would
break backwards compatibility, there are really two options:

1) As already suggested, an alternate kwarg--auto_now_always-- that sets
the default in the database on migration (this solution is super kludgy)
2) An alternate default form--default_db-- that sets a database default.
This couldn't use an arbitrary callable of course, but could use the
database operations module.

auto_now doesn't work as a default and requires a database trigger, so it
either needs to be implemented correctly in Django or the migration system
needs to set these triggers: default_on_update perhaps?

The truth is that suggesting that someone add a database default is the
same as saying: our ORM is broken, use your database... which really
defeats the purpose of the ORM :(

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:6>

Django

unread,
Jul 14, 2020, 10:21:13 AM7/14/20
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: Josh Crompton | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 3.1

(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by MisterGlass):

* version: 1.6 => 3.1


Comment:

Is there an appeals process I can submit to for this ticket to be
reopened? This is still an issue 6 years later. It seems like the only way
to create an auto updated_at field which will work is to add a custom
database trigger to each of my tables.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:7>

Django

unread,
Jul 14, 2020, 10:50:00 AM7/14/20
to django-...@googlegroups.com
#22981: Fields with auto_now=True are not updated if the field name is not present
in update_fields list passed into Model.save
-------------------------------------+-------------------------------------
Reporter: Josh Crompton | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: 3.1
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: | Triage Stage:
| Unreviewed

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Carlton Gibson):

As per the [https://docs.djangoproject.com/en/dev/internals/contributing
/triaging-tickets/#closing-tickets Triage Flow] you can mail the
DevelopersMailingList explaining the issue and why it needs to be re-
opened (and if you have a suggestion that addresses the issues raised all
the better). If agreement is reached there we can reopen.

--
Ticket URL: <https://code.djangoproject.com/ticket/22981#comment:8>

Reply all
Reply to author
Forward
0 new messages