[Django] #27791: update_or_create() doesn't work properly when model has auto_now=True

57 views
Skip to first unread message

Django

unread,
Jan 29, 2017, 8:08:43 AM1/29/17
to django-...@googlegroups.com
#27791: update_or_create() doesn't work properly when model has auto_now=True
-------------------------------------+-------------------------------------
Reporter: Andrew | Owner: nobody
Chiw |
Type: Bug | Status: new
Component: Database | Version: 1.10
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
I'm writing an exchange rate app:

models.py
{{{
from django.db import models


class ExchangeRate(models.Model):
base = models.CharField(max_length=3)
target = models.CharField(max_length=3)
rate = models.DecimalField(max_digits=17, decimal_places=8)
date = models.DateField(auto_now=True)

def __str__(self):
return "{}->{} on {}".format(self.base, self.target,
str(self.date))

class Meta:
unique_together = (("base", "target", "date"),)

}}}

fx.py
{{{
from datetime import datetime, date
import requests

from .models import ExchangeRate


def get_eur_rates():
url = 'http://api.fixer.io/latest'
eur_rates = requests.get(url).json()
print(eur_rates)
for target in eur_rates["rates"]:
import ipdb; ipdb.set_trace()
ExchangeRate.objects.update_or_create(base="EUR", target=target,
date=eur_rates["date"], defaults={"rate": eur_rates["rates"][target]})
print(ExchangeRate.objects.all())
}}}

I already have ExchangeRate objects in the database from 2017-01-29.
Now, when I want to run update_or_create() with date='2017-01-27', it
fails:

{{{
ipdb> ExchangeRate.objects.update_or_create(base="EUR", target=target,
date='2017-01-27', defaults={"rate": eur_rates["
rates"][target]})
*** django.db.utils.IntegrityError: duplicate key value violates unique
constraint "fx_exchangerate_base_f6916782_uniq"
DETAIL: Key (base, target, date)=(EUR, CZK, 2017-01-29) already exists.
}}}

I'm sure Django is working internally in a way that might result in this
error, but this shouldn't happen and the error message is confusing.

--
Ticket URL: <https://code.djangoproject.com/ticket/27791>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jan 30, 2017, 11:53:50 AM1/30/17
to django-...@googlegroups.com
#27791: update_or_create() doesn't work properly when model has auto_now=True
-------------------------------------+-------------------------------------
Reporter: Andrew Chiw | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Tim Graham):

This looks like invalid usage of `auto_now`. As
[https://docs.djangoproject.com/en/stable/ref/models/fields/#django.db.models.DateField.auto_now
the documentation] says, "Automatically set the field to now every time
the object is saved. Useful for “last-modified” timestamps. Note that the
current date is always used; it’s not just a default value that you can
override." It seems like `update_or_create()` can't work intuitively with
an `auto_now` field as whatever value you specify is ignored.

I'm not sure if anything should be done to improve the situation
considering that there are suggestions to deprecate `auto_now`; see #22995
for details and alternatives.

--
Ticket URL: <https://code.djangoproject.com/ticket/27791#comment:1>

Django

unread,
Jan 30, 2017, 4:14:38 PM1/30/17
to django-...@googlegroups.com
#27791: update_or_create() doesn't work properly when model has auto_now=True
-------------------------------------+-------------------------------------
Reporter: Andrew Chiw | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by Ryan Castner):

The fact that you use `unique_together = (("base", "target", "date"),)` is
causing the error you are seeing, it is trying to put two values in there
since auto_now adds the current datetime as Tim stated as well as your
provided datetime value and it can't create two primary keys as it
violates the single unique primary key constraint generated by those three
fields.

--
Ticket URL: <https://code.djangoproject.com/ticket/27791#comment:2>

Django

unread,
Feb 3, 2017, 12:02:04 PM2/3/17
to django-...@googlegroups.com
#27791: update_or_create() doesn't work properly when model has auto_now=True
-------------------------------------+-------------------------------------
Reporter: Andrew Chiw | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.10
(models, ORM) |
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* status: new => closed
* resolution: => invalid


--
Ticket URL: <https://code.djangoproject.com/ticket/27791#comment:3>

Reply all
Reply to author
Forward
0 new messages