交换OneToOneField中的值:IntegrityError

时间:2015-07-22 17:05:53

标签: django django-models

我有以下对象:

from django.db import models

class Page(models.Model):
    prev_sibling = models.OneToOneField('self', related_name='next_sibling',
                                        null=True, blank=True)

我有几个这些对象的实例。我们说A, B, CD。我已经分配了兄弟关系,A Bprev_siblingC Dprev_sibling

现在想象一下我想要交换BD。我只需重新分配属性,如下所示:

A.prev_sibling = D
A.save()
C.prev_sibling = B
C.save()

但是,由于我不再满足IntegrityError在第一个OneToOneField之后隐含的唯一性约束,因此失败了save()

我尝试在事务中包装代码,希望这可以确保保存以原子方式发生,从而防止临时约束违规,如下所示:

from django.db import transaction

with transaction.atomic():
    A.prev_sibling = D
    A.save()
    C.prev_sibling = B
    C.save()

但那没用。解决这个问题的正确方法是什么?

编辑:对于记录:我也尝试过顺序分配然后保存(如下所示),但正如人们所预料的那样,行为也没有区别。

with transaction.atomic():
    A.prev_sibling = D
    C.prev_sibling = B
    A.save()
    C.save()

1 个答案:

答案 0 :(得分:0)

您违反了数据库限制。在保存之前,您需要清除另一个,以便数据库始终处于有效的状态。州。当然,在将它们设置为None之后,它在技术上并不是理想的状态,但它对于数据库约束来说是有效的。

这应该对你有用,但如果在将它们保存为None并设置属性之间发生了不好的事情,你显然有可能失去关系。

Page.objects.filter(id__in=[A.id, C.id]).update(prev_sibling=None)
A.prev_sibling = D
A.save()
C.prev_sibling = B
C.save()