我收到以下错误:
django.db.utils.IntegrityError: duplicate key value violates unique constraint "record_coordinates_lat_lon_created_by_id_key"
DETAIL: Key (lat, lon, created_by_id)=(34.84000015258789, -111.80000305175781, 2) already exists.
背景:到目前为止,我一直在使用MySQL和Django 1.4.3。现在我已经安装了Postgres 9.3和Psycopg2 2.5.2。验证和Syncdb工作正常。南没有安装。
我运行了一个脚本(适用于MySQL)。该脚本循环通过GPS文件并将lat / lon数据保存在坐标表中。
_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,
modified_by=self._user,
date_created=datetime.now(), # See Update 2 addition below.
)
我在模型定义中有unique_together = ('lat', 'lon', )
约束。一些坐标是相同的(因此使用get_or_create())。我发现自己摸不着头脑,因为它应该“获得”坐标而不是试图“创造”新坐标。
本网站关于Postgres和Django的大多数问题几乎不可避免地提到南方。我需要南方,还是其他什么东西在这里?我只是想在不安装迁移的情况下进行快速而肮脏的测试。
更新1:
我试过的其他事情就是suggestion of another post在Postgres上运行SELECT setval('django_content_type_id_seq', (SELECT MAX(id) FROM django_content_type));
。错误仍然存在。
更新2: 好吧,我没有意识到我需要将所有的Coordinates字段放在默认值dict中。 Coordinates模型包含另一个字段'date_created = models.DateTimeField(auto_now_add = True)'
我发现以下blog post似乎解释了当你使用'auto_now_add = True'时get_or_create()会中断。现在最大的问题是如何使用auto_now_add而不破坏get_or_create()?
答案 0 :(得分:2)
你错过了defaults
的论点
get_or_create致电。然后,如果数据库中没有指定lat
lon
的记录,它将使用默认lat
,lon
创建一条新记录,这显然不是自动生成并获得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,
)
)
由于唯一索引由列lat
,lon
和created_by
(查看错误中的索引名称)组成,因此您应该在{{的过滤器中使用所有这些列1}}。
答案 1 :(得分:2)
这回答了我的问题。
_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,
)
auto_now
和auto_now_add
就好了。事实证明,我的所有默认值都已在模型上定义。
问题在于,当我将group[u'lat']
和group[u'lon']
放入字典时,它们都被转换为浮点数。相比之下,lat
和lon
都定义为DecimalFields()
。
使用MySQL时,我可以将这些浮点值与数据库的内容进行比较。但是,当我使用Postgres时,get()
的{{1}}部分会尝试将数据库中的Decimal值与我提供的浮点值进行比较。类型被更强烈地解释,并且在比较期间不会将float转换为Decimal。
在我的调试器中,我看到了:
get_or_create()
如果django能够产生像{Decimal}lat
{float}group[lat]