如何在创建失败时阻止Django / PSQL自动递增表ID

时间:2017-09-05 08:04:44

标签: python django postgresql psql

目前,我有一个带有ItemReport表的Django项目,每个项目每天只允许1个条目。一切都很好,除了每当它失败并出现IntegrityError(即我的项目试图在ItemReport已经存在的那一天创建ItemReport时,对象ID无论如何都会增加。

例如:

September 1:
 Report for September 1 (ID 1)

September 2:
 Report for September 1 (ID 1)
 Report for September 2 (ID 5)

模型如下:

class ItemReport(BaseModel):
    fk_item: Item = models.ForeignKey(Item, null=False)
    date = models.DateField(default=now, null=False)

    class Meta:
        unique_together=(('fk_item', 'date'),)


class Item(BaseModel):
    item_class = models.CharField(max_length=40, null=False)
    name = models.CharField(max_length=80, unique=True, null=False)

每次用户登录时运行的代码:

    for i in Item.objects.all():
        try:
            latest_ir = ItemReport.objects.create(fk_item=i)
            print('Created Item Report!')
        except IntegrityError as e:
            print('ItemReport for {} for today already exists!'.format(i.name))
    print('Created ItemReports!\n')

2 个答案:

答案 0 :(得分:2)

问了问题三年后,我遇到了同样的问题,发现还没有得到解决,我想在这里留下我如何为将来的访客解决问题。

以前,我使用以下代码来防止重复错误。

try:
    m = Modal(title='Title', content='Content.')
    m.save()
except IntegrityError:
    pass

但是,无论您遇到什么问题,只要IntegrityError失败,对象ID就会不断增加。

我通过删除try/except块并使用get_or_create()而不是save()来解决了这个问题。

Modal.objects.get_or_create(title='Title', content='Content.')

Django文档中的get_or_create()方法的详细说明: https://docs.djangoproject.com/en/3.1/ref/models/querysets/#get-or-create

答案 1 :(得分:1)

如果pk是自动增量字段,则无法执行此操作。当您尝试创建新对象时,数据库获取值表单序列。并且序列不支持回滚,因为当许多用户同时插入新行,并且只有一个被中止时,对于重建序列,在数据库中需要很多硬操作。

希望对你有所帮助。