# 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
--
Ticket URL: <https://code.djangoproject.com/ticket/22571>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* component: Uncategorized => Documentation
* needs_tests: => 0
* needs_docs: => 0
* type: Uncategorized => Cleanup/optimization
* stage: Unreviewed => Accepted
Comment:
I suppose the documentation could have a note about this.
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:1>
Comment (by MarkusH):
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 `()`).
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:2>
Old description:
New description:
print created
# >> True
print created
# >> False
http://stackoverflow.com/questions/9297422/get-or-create-failure-with-
django-and-postgres-duplicate-key-value-violates-uni
--
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:3>
Comment (by mardini):
Note that your date_added is a DateTimeField, not a DateField, so it takes
time into account. That's why using "today's date" won't match the
existing value of date_added (since it's today's date + a particular
time). If however some_datetime_obj in your first is exactly the same date
and time, no new object will be created. If you don't want to consider the
time in your get_or_create(), you can either use a DateField for
date_added, or filter against year/month/day of your DateTimeField. So I
think this ticket is invalid.
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:4>
Comment (by charettes):
Replying to [comment:4 mardini]:
> Note that your date_added is a DateTimeField, not a DateField, so it
takes time into account. That's why using "today's date" won't match the
existing value of date_added (since it's today's date + a particular
time). If however some_datetime_obj in your first is exactly the same date
and time, no new object will be created. If you don't want to consider the
time in your get_or_create(), you can either use a DateField for
date_added, or filter against year/month/day of your DateTimeField. So I
think this ticket is invalid.
I agree that the second example is a bit wrong but there's a legitimate
issue to be documented here.
{{{#!python
from django.db import models
from django.utils import timezone
class Auto(models.Model):
added = models.DateTimeField(auto_now_add=True)
class Default(models.Model):
added = models.DateTimeField(default=timezone.now)
}}}
{{{#!python
In [1]: from app.models import Auto, Default, timezone
In [2]: added = timezone.now()
In [3]: Auto.objects.get_or_create(added=added)
Out[3]: (<Auto: Auto object>, True)
In [4]: Auto.objects.get_or_create(added=added)
Out[4]: (<Auto: Auto object>, True)
In [5]: Default.objects.get_or_create(added=added)
Out[5]: (<Default: Default object>, True)
In [6]: Default.objects.get_or_create(added=added)
Out[6]: (<Default: Default object>, False)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:5>
* cc: me@… (added)
Comment:
Replying to [comment:5 charettes]:
> {{{#!python
> In [1]: from app.models import Auto, Default, timezone
>
> In [2]: added = timezone.now()
>
> In [3]: Auto.objects.get_or_create(added=added)
> Out[3]: (<Auto: Auto object>, True)
>
> In [4]: Auto.objects.get_or_create(added=added)
> Out[4]: (<Auto: Auto object>, True)
>
> In [5]: Default.objects.get_or_create(added=added)
> Out[5]: (<Default: Default object>, True)
>
> In [6]: Default.objects.get_or_create(added=added)
> Out[6]: (<Default: Default object>, False)
> }}}
Isn't this expected? The doc says -
> DateField.auto_now_add
>
> Automatically set the field to now when the object is first created.
Useful for creation of timestamps. Note that the current date is *always*
used; it’s not just a default value that you can override.
And the code also shows that the value with always set to `timezone.now()`
if `auto_now_add` is set, even if you provide a value when creating it.
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:6>
* owner: nobody => yamila-moreno
* status: new => assigned
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:7>
* has_patch: 0 => 1
Comment:
PR: https://github.com/django/django/pull/4792
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:8>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"cbe4efcbc13ad402bf1f1a94b02a8ec93f20327d" cbe4efc]:
{{{
#!CommitTicketReference repository=""
revision="cbe4efcbc13ad402bf1f1a94b02a8ec93f20327d"
Fixed #22571 -- Added clarification about auto_now_add=True
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:9>
Comment (by Tim Graham <timograham@…>):
In [changeset:"7dcfbb2ef38bb806531d6e73dd179d5266f48d7a" 7dcfbb2e]:
{{{
#!CommitTicketReference repository=""
revision="7dcfbb2ef38bb806531d6e73dd179d5266f48d7a"
[1.8.x] Fixed #22571 -- Added clarification about auto_now_add=True
Backport of cbe4efcbc13ad402bf1f1a94b02a8ec93f20327d from master
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/22571#comment:10>