У меня есть ряд моделей Django как показано в следующей схеме (названия обратных отношений показывают в желтых пузырях):
(источник: cbstaff.com)
В каждых отношениях, a Person
может иметь 0 или больше из объектов.
Кроме того, slug
поле (к сожалению), не уникально; несколько Person
записи могут иметь те же поля краткого заголовка. По существу эти записи являются дубликатами.
Я хочу получить список всех записей, которые соответствуют следующим критериям: Все дублирующиеся записи (то есть, имея тот же краткий заголовок) по крайней мере с одним Entry
ИЛИ по крайней мере один Audio
ИЛИ по крайней мере один Episode
ИЛИ по крайней мере один Article
.
До сих пор у меня есть следующий запрос:
Person.objects.values('slug').annotate(num_records=Count('slug')).filter(num_records__gt=1)
Это группирует все записи slug
, затем добавляет a num_records
атрибут, который говорит, сколько записей имеет тот краткий заголовок, но дополнительная фильтрация не выполняется (и я даже не знаю, работало ли это правильно так или иначе, с тех пор, учитывая ряд дублирующихся записей, можно иметь, например, и Entry
и другой может иметь Article
).
Короче говоря я хочу найти все дублирующиеся записи и свернуть их, наряду с их связанными моделями, в одну запись.
Что лучший способ состоит в том, чтобы сделать это с Django?
Я бы сделал это в нескольких запросах. Первый - это ваш список дубликатов, который у вас есть:
dupes = [p['slug'] for p in Person.objects.values('slug').annotate(num_records=Count('slug')).filter(num_records__gt=1)]
Затем я бы перебрал их и для каждого решил, какие из них оставить (примите произвольное решение - выберите первый). Затем для всех других первичных ключей просто обновите все другие объекты, чтобы они указывали на первичный ключ, который вы выбрали:
for slug in dupes:
pks = [p.id for p in Person.objects.filter(slug=slug)]
for pk in pks[1:]:
Audio.objects.filter(person=pk).update(person=pks[0])
Author.objects.filter(person=pk).update(person=pks[0])
Episode.objects.filter(person=pk).update(person=pks[0])
Entry.objects.filter(person=pk).update(person=pks[0])
Вы смотрели на агрегацию Django для 'group by', как поведение?
Я не уверен, что объединение фильтров в цепочку поможет вам достичь желаемого результата, поскольку будут записи Person, в которых есть два или более типов артефактов с их названием. Посмотрите на предыдущий вопрос на StackOverflow и ответ на него, который, я думаю, поможет вам объединить четыре запроса в один QuerySet так, как вы хотите:
Как объединить 2 или более наборов запросов в представлении Django?