I have a model like this:
class FooBar(models.Model):
createtime = models.DateTimeField(auto_now_add=True)
lastupdatetime = models.DateTimeField(auto
You can override auto_now_add
without special code.
I came across this question when I tried to create an object with particular date:
Post.objects.create(publication_date=date, ...)
where publication_date = models.DateField(auto_now_add=True)
.
So this is what I've done:
post = Post.objects.create(...)
post.publication_date = date
post.save()
This has successfully overridden auto_now_add
.
As a more long-term solution, overriding save
method is the way to go: https://code.djangoproject.com/ticket/16583
I needed solution that will work with update_or_create
, I've came to this solution based on @andreaspelme code.
Only change is that You can set skipping by setting modified field to skip
not only by actually passing kwarg skip_modified_update
to save() method.
Just yourmodelobject.modified='skip'
and update will be skipped!
from django.db import models
from django.utils import timezone
class TimeTrackableAbstractModel(models.Model):
created = models.DateTimeField(default=timezone.now, db_index=True)
modified = models.DateTimeField(default=timezone.now, db_index=True)
class Meta:
abstract = True
def save(self, *args, **kwargs):
skip_modified_update = kwargs.pop('skip_modified_update', False)
if skip_modified_update or self.modified == 'skip':
self.modified = models.F('modified')
else:
self.modified = timezone.now()
super(TimeTrackableAbstractModel, self).save(*args, **kwargs)
You can also use the update_fields
parameter of save()
and pass your auto_now
fields. Here's an example:
# Date you want to force
new_created_date = date(year=2019, month=1, day=1)
# The `created` field is `auto_now` in your model
instance.created = new_created_date
instance.save(update_fields=['created'])
Here's the explanation from Django's documentation: https://docs.djangoproject.com/en/stable/ref/models/instances/#specifying-which-fields-to-save
I'm late to the party, but similar to several of the other answers, this is a solution I used during a database migration. The difference from the other answers is that this disables all auto_now fields for the model under the assumption that there's really no reason to have more than one such field.
def disable_auto_now_fields(*models):
"""Turns off the auto_now and auto_now_add attributes on a Model's fields,
so that an instance of the Model can be saved with a custom value.
"""
for model in models:
for field in model._meta.local_fields:
if hasattr(field, 'auto_now'):
field.auto_now = False
if hasattr(field, 'auto_now_add'):
field.auto_now_add = False
Then to use it, you can simply do:
disable_auto_now_fields(Document, Event, ...)
And it will go through and nuke all of your auto_now
and auto_now_add
fields for all of the model classes you pass in.
I used the suggestion made by the asker, and created some functions. Here is the use case:
turn_off_auto_now(FooBar, "lastupdatetime")
turn_off_auto_now_add(FooBar, "createtime")
new_entry.createtime = date
new_entry.lastupdatetime = date
new_entry.save()
Here's the implementation:
def turn_off_auto_now(ModelClass, field_name):
def auto_now_off(field):
field.auto_now = False
do_to_model(ModelClass, field_name, auto_now_off)
def turn_off_auto_now_add(ModelClass, field_name):
def auto_now_add_off(field):
field.auto_now_add = False
do_to_model(ModelClass, field_name, auto_now_add_off)
def do_to_model(ModelClass, field_name, func):
field = ModelClass._meta.get_field_by_name(field_name)[0]
func(field)
Similar functions can be created to turn them back on.
For those looking at this when they are writing tests, there is a python library called freezegun which allows you to fake the time - so when the auto_now_add
code runs, it gets the time you actually want. So:
from datetime import datetime, timedelta
from freezegun import freeze_time
with freeze_time('2016-10-10'):
new_entry = FooBar.objects.create(...)
with freeze_time('2016-10-17'):
# use new_entry as you wish, as though it was created 7 days ago
It can also be used as a decorator - see the link above for basic docs.