【问题标题】:Migrate Django model to unique_together constraint将 Django 模型迁移到 unique_together 约束
【发布时间】:2012-01-05 09:58:33
【问题描述】:

我有一个包含三个字段的模型

class MyModel(models.Model):
    a    = models.ForeignKey(A)
    b    = models.ForeignKey(B)
    c    = models.ForeignKey(C)

我想在这些字段之间强制执行唯一约束,并找到了 django 的 unique_together,这似乎是解决方案。但是,我已经有一个现有的数据库,并且有很多重复项。我知道由于unique_together 在数据库级别工作,我需要对行进行唯一化,然后尝试迁移。

有没有一种好方法可以删除重复项(其中重复项具有相同的 (A、B、C)),以便我可以运行迁移以获取 unique_together 约束?

【问题讨论】:

  • 您的模型上是否还有其他字段(可能会影响选择保留哪个副本)?
  • 我有一个 created_at 时间,这可能是最好的指标

标签: django migration unique-constraint django-south


【解决方案1】:

如果您乐于任意选择其中一个副本,我认为以下方法可能会奏效。也许不是最有效但足够简单,我猜你只需要运行一次。请验证这一切都适用于一些测试数据,以防我做了一些愚蠢的事情,因为你即将删除一堆数据。

首先我们找到形成重复的对象组。对于每个组,(任意)选择一个我们要保留的“主人”。我们选择的方法是选择最低的pk

from django.db.models import Min, Count

master_pks = MyModel.objects.values('A', 'B', 'C'
    ).annotate(Min('pk'), count=Count('pk')
    ).filter(count__gt=1
    ).values_list('pk__min', flat=True)

然后我们循环遍历每个 master,并删除其所有重复项

masters = MyModel.objects.in_bulk( list(master_pks) )

for master in masters.values():
    MyModel.objects.filter(a=master.a, b=master.b, c=master.c
        ).exclude(pk=master.pk).del_ACCIDENT_PREVENTION_ete()

【讨论】:

  • 我们可以在迁移文件本身中做类似的事情来避免运行额外的脚本吗?
  • 什么是.del_ACCIDENT_PREVENTION_elte()
  • delete 在中间添加了短语ACCIDENT_PREVENTION 以防止人们在不阅读代码的情况下通过复制/粘贴代码意外删除内容
  • @chhantyal 把它放在一个迁移文件中。查看 Django 文档以了解数据迁移。我刚做了一个,尽可能简单。
猜你喜欢
  • 2010-11-03
  • 2017-12-08
  • 2015-05-25
  • 2019-01-08
  • 2017-04-09
  • 2019-07-12
  • 2015-04-24
  • 2021-12-29
  • 1970-01-01
相关资源
最近更新 更多