How do I fix django.db.utils.IntegrityError: duplicate key value violates unique constraint?
Rise to the top 3% as a developer or hire one of them at Toptal: https://topt.al/25cXVn
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Dreamlands
--
Chapters
00:00 How Do I Fix Django.Db.Utils.Integrityerror: Duplicate Key Value Violates Unique Constraint?
02:17 Answer 1 Score 2
02:59 Accepted Answer Score 3
04:02 Thank you
--
Full question
https://stackoverflow.com/questions/2343...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #mysql #django #postgresql #psycopg2
#avk47
ACCEPTED ANSWER
Score 3
This answered my question.
_coordinates, coordinates_created = Coordinates.objects.get_or_create(
lat=Decimal(group[u'lat'])._rescale(-Coordinates.max_decimal_places, 'ROUND_HALF_EVEN'),
lon=Decimal(group[u'lon'])._rescale(-Coordinates.max_decimal_places, 'ROUND_HALF_EVEN'),
created_by=self._user,
modified_by=self._user,
)
The auto_now and auto_now_add were just fine. It turns out that all of my defaults are already defined on the Model.
The problem was that group[u'lat'] and group[u'lon'] were both cast as floats when I placed them in my dictionary. In contrast, lat and lon are both defined as DecimalFields().
When using MySQL I can compare these float values against the contents of the database just fine. However, when I use Postgres the get() portion of get_or_create() attempts to compare a Decimal value from the database with the the float values I was providing it. The types are interpreted more strongly, and the float will not be cast to a Decimal during the comparison.
In my debugger, I saw:
{Decimal}lat
{float}group[lat]
It would be nice if django could produce a clear error like TypeError: Can't compare Decimal with float.
ANSWER 2
Score 2
You missed defaults argument in the
get_or_create call. Then, if there is no record in the db with the specified lat, lon, it will create a new record with the default lat, lon, which obviously are not autogenerated and you get the IntegrityError.
_coordinates, coordinates_created = Coordinates.objects.get_or_create(
lat=round(group[u'lat'], Coordinates.max_decimal_places),
lon=round(group[u'lon'], Coordinates.max_decimal_places),
created_by=self._user,
defaults=dict(
lat=round(group[u'lat'], Coordinates.max_decimal_places),
lon=round(group[u'lon'], Coordinates.max_decimal_places),
created_by=self._user,
modified_by=self._user,
)
)
As the unique index consist of columns lat, lon and created_by (looking at the index name from the error), you should use all of them in the filters of get_or_create.