Opened 10 years ago

Last modified 9 years ago

#22571 closed Cleanup/optimization

Document implications of using auto_now_add=True and get_or_create — at Version 3

Reported by: nu.everest@… Owned by: nobody
Component: Documentation Version: 1.4
Severity: Normal Keywords: integrityerror auto_now_add get_or_create duplicatekey
Cc: me@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Russell Keith-Magee)

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 messes 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

Error:
django.db.utils.IntegrityError: duplicate key value violates unique constraint

These two links document the issue:
http://alexkehayias.tumblr.com/post/33889961953/django-gotcha-duplicate-models-when-using

http://stackoverflow.com/questions/9297422/get-or-create-failure-with-django-and-postgres-duplicate-key-value-violates-uni

Change History (3)

comment:1 by Tim Graham, 10 years ago

Component: UncategorizedDocumentation
Summary: DateTimeField(auto_now_add=True) BreaksDocument implications of using auto_now_add=True and get_or_create
Triage Stage: UnreviewedAccepted
Type: UncategorizedCleanup/optimization

I suppose the documentation could have a note about this.

comment:2 by Markus Holtermann, 10 years ago

Your solution is not a solution at all, because your default on the DateTimeField is evaluated only once at model loading. You can use Django's django.utils.timezone.now (w/o the trailing ()).

comment:3 by Russell Keith-Magee, 10 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top