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

时间:2014-07-25 20:27:26

标签: python django postgresql

我的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 个答案:

答案 0 :(得分:1)

这是我获得您要求的现有记录的方式。 在这种情况下,我有

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

我使用正则表达式获取导致问题的现有记录的所有者和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'))

答案 1 :(得分:0)

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

我想无论如何

答案 2 :(得分: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(类似于IntegrityError: distinguish between unique constraint and not null violations中接受的答案,这将是很好的(并且可能但我没有尝试过)) ,它也有缺点似乎只是postgres)来确定哪些字段违反了。请注意,如果您想要遵循原始框架,则可以在异常中执行collidedObject = Business.objects.get(name=b['name']),但这仅适用于您确定知道它是名称冲突的情况。