jazzband/django-model-utils

AutoLastModifiedField default caching keeps the first time called value

nesaro opened this issue · 0 comments

Problem

AutoLastModifiedField caches the default value for new entries rather than calling now every time.

Environment

  • Django Model Utils version: >= 4.0.0
  • Django version: Tested on 2.2 and 3.0
  • Python version: 3.8

Code examples

class MyModel(models.Model):
    my_field = AutoLastModifiedField()

with freezegun.freezetime(time1):
    instance1 = MyModel()
with freezegun.freezetime(time2):
    instance2 = MyModel()

assert(instance1.my_field != instance2.my_field) # this will fail

Explanation

AutoLastModifiedField has a cache for the default value

    def get_default(self):
        """Return the default value for this field."""
        if not hasattr(self, "_default"):
            self._default = self._get_default()
        return self._default

This overrides the base django field get_default by always returning the value stored on the first call of save()

I noticed this while upgrading the version and running tests with various freezed time values. My temporary solution was to remove the cache.

del MyModel._meta.get_field('modified')._default

This bug was introduced in version 4.0.0 1878537

I do not understand the purpose of caching the value, but my suggestion is to remove the caching or to keep the django logic that caches the value if not callable.

    def get_default(self):
        """Return the default value for this field."""
        return self._get_default()

    @cached_property
    def _get_default(self):
         if callable(self.default):
             return self.default
          return lambda: self.default