如何在Django中更新具有唯一约束的对象列表?

2 投票
2 回答
865 浏览
提问于 2025-04-18 14:06

我正在尝试更新一个有唯一约束的对象列表,但出现了异常。请问在使用Django的ORM时,有办法延迟约束的检查吗?

这是我尝试过的:

class Episode(models.Model):
    issue_date = models.DateTimeField(db_index=True, unique=True)
    ...
def rearrange_episodes(cls, programme, after):
    next_episodes = Episode.objects.filter(programme=programme, issue_date__gte=after).order_by('issue_date')
    for episode in next_episodes:
        episode.issue_date = get_next_date()
        episode.save() #Crash -> Duplicate entry

2 个回答

0

这个解决方案对我的问题不适用,因为重新排列的方式不是线性的。

举个例子:

episode[4].issue_date --> new date 
episode[3].issue_date --> previous episode[4].issue_date 
episode[2].issue_date --> not change
episode[1].issue_date --> previous episode[0].issue_date
episode[0].issue_date --> new date

我只想到两种简单的方法来解决这个问题,要么去掉限制,要么使用 bulk_create 删除并重新创建对象。

1

如果 get_next_date() 函数返回的日期已经存在,那你就遇到了一个无法解决的问题。

我假设你想要的是把日期往后推一个“集数”,也就是说:

episode[0].issue_date --> episode[1].issue_date
episode[1].issue_date --> episode[2].issue_date
episode[2].issue_date --> new date

...你已经尝试这样做了,但在第一步就失败了,因为 episode[1].issue_date 已经存在。

要解决这个问题,你只需要反向遍历,这样:

episode[2].issue_date --> new date
episode[1].issue_date --> previous episode[2].issue_date
episode[0].issue_date --> previous episode[1].issue_date

假设你的 get_next_date() 函数在这种情况下可以正常工作,你只需要把代码改成:

def rearrange_episodes(cls, programme, after):
    next_episodes = Episode.objects.filter(programme=programme, issue_date__gte=after).order_by('-issue_date')
    for episode in next_episodes:
        episode.issue_date = get_next_date()
        episode.save()

撰写回答