Django Gotcha: Duplicate models when using get_or_create

When you’re saving some object to the db, there’s a gotcha with DateTimeFields that drove me nuts. It took me way too long to figure this out, but if you have a DateTimeField with the option auto_now_add, it will supersede a datetime object in a Model.objects.get_or_create call. This means that if you are tying to prevent duplicates based on date (say you’re saving some data from an API that has a timestamp) you will still get duplicates. It’s in the docs, but not the implications when using get_or_create. Check out this example:

# Given this simple model
class Foo(models.Model):
    name = models.CharField(max_length=100)
    date_added = models.DateTimeField(auto_now_add=True)

# This will always be true, even if an instance
# with this name and today's date already exists

bar, created = Foo.objects.get_or_create(
    name = 'Alex', 
    date_added = some_datetime_obj
)

print created
# >> True


# The problem is, auto_now_add does some stuff that 
# makes it uneditable, and fucks up my expectations
# when using it with get_or_create

# Here's the solution
class Foo(models.Model):
    name = models.CharField(max_length=100)
    date_added = models.DateTimeField(default=datetime.today())

bar, created = Foo.objects.get_or_create(
    name = 'Alex', 
    date_added = some_datetime_obj
)

print created
# >> False