Перенос модели Django в ограничение unique_together - PullRequest
9 голосов
/ 24 ноября 2011

У меня есть модель с тремя полями

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 contstraint?

1 Ответ

25 голосов
/ 24 ноября 2011

Если вы счастливы выбрать один из дубликатов произвольно, я думаю, что следующее может помочь.Возможно, не самый эффективный, но достаточно простой, и я думаю, вам нужно запустить его только один раз.Пожалуйста, убедитесь, что все это работает на некоторых тестовых данных на случай, если я сделал что-то глупое, поскольку вы собираетесь удалить кучу данных.

Сначала мы находим группы объектов, которые образуют дубликаты.Для каждой группы (произвольно) выберите «мастера», который мы собираемся сохранить.Наш выбранный метод состоит в том, чтобы выбрать тот, который имеет наименьшее значение 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)

, затем мы зациклим каждый мастер и удалим все его дубликаты

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()
...