【问题标题】:get_or_create fails for unique_together for decimalsget_or_create 对于 unique_together 的小数失败
【发布时间】:2020-05-28 13:02:19
【问题描述】:

我有以下型号:

class LocationPoint(models.Model):
    latitude = models.DecimalField(max_digits=9, decimal_places=6)
    longitude = models.DecimalField(max_digits=9, decimal_places=6)

    class Meta:
        unique_together = (
            ('latitude', 'longitude',),
        )

交互者:

class GetOrCreateLocationPoint(object):

    def exec(self, latitude: Decimal, longitude: Decimal) -> LocationPoint:
        point, _ = LocationPoint.objects.get_or_create(
            latitude=latitude,
            longitude=longitude,

            defaults={
                'latitude': latitude,
                'longitude': longitude,
            },
        )

        return point

并测试:

class GetOrCreateLocationPointTest(TestCase): # from django.test import TestCase
    __get_or_create_location_point: GetOrCreateLocationPoint

    def setUp(self) -> None:
        self.__get_or_create_location_point = GetOrCreateLocationPoint()

    def test_create_duplicate(self):
        point1 = self.__get_or_create_location_point.exec(Decimal(10.5), Decimal(5.01))
        self.__get_or_create_location_point.exec(Decimal(13.4), Decimal(1.5343))
        point3 = self.__get_or_create_location_point.exec(Decimal(10.5), Decimal(5.01))

        self.assertEqual(point1.pk, point3.pk)

执行point3 = self.__get_or_create_location_point.exec(Decimal(10.5), Decimal(5.01))时出错:

django.db.utils.IntegrityError: duplicate key value violates unique constraint "geo_locationpoint_latitude_longitude_08fb2a82_uniq"
DETAIL:  Key (latitude, longitude)=(10.500000, 5.010000) already exists.

但是,如果在调试器中我看到self.model.DoesNotExist 在get_or_create 中被抛出(并处理),则它找不到现有行。

怎么了?

Django 3.0.3,PostgreSQL 12。

【问题讨论】:

  • 我有点迷茫,是get_or_create扔IntegrityError还是DoesNotExist?
  • @AustinPilp 它在内部处理 DoesNotExist(参见 get_or_create 实现),尝试创建新行,然后引发 IntegrityError
  • 明白了,我不确定这是否能解决您的问题,但您实际上不需要提供纬度和经度作为默认值。由于它们已经是查找参数,因此它们将包含在新对象中。文档的相关部分 (docs.djangoproject.com/en/3.0/ref/models/querysets/…) 提供了一个有用的“等效代码”示例,说明了如何使用每个参数
  • 真可惜,我现在在一台装有 Django 的机器附近,但如果今晚我回家时没有人帮助你,我会试着玩一下,看看能不能弄清楚任何事情。祝你好运!
  • @AustinPhilp 大声笑,刚刚修复它,问题出在浮动中,看看我的回答:D

标签: django postgresql psycopg2 django-orm


【解决方案1】:

嗯,它似乎失败了,因为在 Decimal 构造函数中使用了浮点数……

用字符串表示替换浮点数解决了这个问题:

    def test_create_duplicate(self):
        point1 = self.__get_or_create_location_point.exec(Decimal('10.5'), Decimal('5.01'))
        self.__get_or_create_location_point.exec(Decimal('13.4'), Decimal('1.5343'))
        point3 = self.__get_or_create_location_point.exec(Decimal('10.5'), Decimal('5.01'))

        self.assertEqual(point1.pk, point3.pk)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-18
    • 2010-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    相关资源
    最近更新 更多