Иногда случается, что при создании моделей мы забываем про ключи для обеспечения уникальности полей. А вспоминаем об этом только когда начинают сыпаться ошибки из-за накопившихся дублей.
Эта заметка о решении этой проблемы "одним ударом"
Для этого мы сделаем самописную миграцию с небольшой функцией для удаления дублей:
import django.core.validators
from django.db import migrations, models
def _del_double(apps, schema_editor):
'''
Функция удаляющая из модели все дубли.
Дубли ищем по составному уникальному ключу из двух полей
key_1 и key_2
'''
MyModel = apps.get_model("<My_app>", "<My_model>")
for record in MyModel.objects.values('key_1', 'key_2').distinct():
# Накапливаем список дублей
double_list = UserSettings.objects.filter(
key_1=record['key_1'],
key_2=record['key_2']
).values_list('id', flat=True)[1:]
# Поочередно удаляем дубли
for double_pk in double_list:
MyModel.objects.exclude(value__isnull=True).filter(
pk=double_pk
).delete()
class Migration(migrations.Migration):
'''
Миграция объединяющая удаление дублей и последующее создание
уникальных ключей
'''
dependencies = [
('<My_app', '<Previous_migration>'),
]
operations = [
migrations.RunPython(_del_double),
migrations.AlterUniqueTogether(
name='mymodel',
unique_together=set([('key_1', 'key_2')]),
),
]
Также не забываем добавить в нашу модель:
class MyModel(models.Model):
class Meta:
unique_together = ('key_1', 'key_2')
Вот и всё. После запуска мы получим модель очищенную от дублей и готовую к дальнейшей работе без дублей.
Комментарии