如何获取导致Django中IntegrityError的记录

2 投票
3 回答
1795 浏览
提问于 2025-04-18 14:48

我在我的Django模型中有以下内容,使用的是PostgresSql。

class Business(models.Model):
    location = models.CharField(max_length=200,default="")
    name = models.CharField(max_length=200,default="",unique=True)

在我的视图中,我有:

for b in bs: 
    try:
        p = Business(**b)
        p.save()
    except IntegrityError:
        pass

当应用程序运行时,如果出现了完整性错误(IntegrityError),我想获取已经插入的记录,以及触发错误的对象(我猜是'p'),然后更新位置字段。

用伪代码表示就是:

for b in bs: 
    try:
        p = Business(**b)
        p.save()
    except IntegrityError:

     EXISTING_RECORD.location = EXISTING_RECORD.location + p.location
     EXISTING_RECORD.save()

在Django中怎么实现这个呢?

3 个回答

-1
for b in bs: 
    p = Business.objects.get_or_create(name=b['name'])
    p.update(**b)
    p.save()

我觉得无论如何

0

我试过使用 get_or_create,但这并不能完全达到你的要求(如果你用名字和地点一起做 get_or_create,还是会出现完整性错误;如果按照 Joran 的建议去做,除非你重载更新功能,否则会把地点覆盖掉,而不是追加)。

这样做应该能符合你的需求:

for b in bs: 
    bobj, new_flag = Business.objects.get_or_create(name=b['name'])
    if new_flag:
       bobj.location = b['location']
    else:
       bobj.location += b['location'] # or possibly something like += ',' + b['location'] if you wanted to separate them
    bobj.save()

如果你可以有多个唯一约束,能够检查完整性异常(IntegrityException)会很好(可能是可行的,但我还没试过),就像在这个完整性错误:区分唯一约束和非空约束的回答中提到的那样,这也有个缺点,就是看起来只有 Postgres 支持)。需要注意的是,如果你想遵循最初的框架,可以在异常处理中使用 collidedObject = Business.objects.get(name=b['name']),但这只在你确定是名字冲突的情况下有效。

2

这是我获取你所提到的现有记录的方法。
在这个例子中,我有一个叫 MyModel 的模型,里面包含了以下内容:

unique_together = (("owner", "hsh"),)

我使用正则表达式来获取导致问题的现有记录的拥有者和哈希值。

import re
from django.db import IntegrityError


try:
    // do something that might raise Integrity error

except IntegrityError as e:

    #example error message (e.message): 'duplicate key value violates unique constraint "thingi_userfile_owner_id_7031f4ac5e4595e3_uniq"\nDETAIL:  Key (owner_id, hsh)=(66819, 4252d2eba0e567e471cb08a8da4611e2) already exists.\n'

    import re
    match = re.search( r'Key \(owner_id, hsh\)=\((?P<owner_id>\d+), (?P<hsh>\w+)\) already', e.message)
    existing_record = MyModel.objects.get(owner_id=match.group('owner_id'), hsh=match.group('hsh'))

撰写回答