Disable `auto_now_add` temporarily in a command

Hello everybody, sorry I don’t know exactly in which forum to ask that question.

Here is a simple model for a user action:

class UserAction(models.Model):
    action = models.CharField(...)
    created_at = models.DateTimeField(auto_now_add=True)

For development purpose, I want to make a command to run periodically that fakes user activity throughout the day. In other words, daily at say 8:00 in the morning, my script will bulk create like thousands of UserAction rows for the day, each with different fake created_at values.

The problem is, auto_now_add doesn’t let me save a date manually. Instead, the value will always be the date of creation of the row. auto_now_add is a requirement that cannot be permanently removed from the model.

How could I sort of disable that behaviour just the time it takes to run that script? Basically what I’d see for my command is something like this:

@transaction.atomic

  1. create UserAction instances
  2. disable auto_now_add
  3. bulk create UserAction rows
  4. enable auto_now_add

Is that doable?

In [3]: r = ReportedTime.objects.all().first()

In [4]: r.ts
Out[4]: datetime.datetime(2023, 10, 5, 12, 47, 55, 425039, tzinfo=datetime.timezone.utc)

In [5]: r.ts = now()

In [6]: r.save()

In [7]: r.refresh_from_db()

In [8]: r.ts
Out[8]: datetime.datetime(2024, 10, 21, 14, 42, 13, 431365, tzinfo=datetime.timezone.utc)

Looks to me like you can edit them just fine. What is the problem you’re having?

I’m having the behaviour as described here in the docs:

Maybe I can still overwrite the field after creation of the row, but it seems not at creation of the row, or at least not using bulk_create.

# Create
>>> unique_actions = [UserAction(created_at="2010-01-01", action="unique action") for x in range(10)]
>>> UserAction.objects.bulk_create(unique_actions)

# Get
>>> unique_actions = UserAction.objects.filter(action="unique action").values_list("created_at__date", flat=True)
>>> pprint(list(unique_actions))
[datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21),
 datetime.date(2024, 10, 21)]

That is correct, as far as creating the objects using the ORM. You could create those rows with custom values if you created them using raw sql.

Hi Ken, as always thanks for super fast reply.

Actually it looks like the answer was super simple. Contrary to my assumption, auto_now_add is not enforced at DB level. So just “disable” it in the model field in the script.

# my_script.py
# Prepare
>>> UserAction.created_at.field.auto_now_add = False

# Create
>>> unique_actions = [UserAction(created_at="2010-01-01", action="unique action") for x in range(10)]
>>> UserAction.objects.bulk_create(unique_actions)

# Get
>>> unique_actions = UserAction.objects.filter(action="unique action").values_list("created_at__date", flat=True)
>>> pprint(list(unique_actions))
 [datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1),
 datetime.date(2010, 1, 1)]

# Exit
1 Like