order_by в поле "многие ко многим" приводит к дублированию записей в наборе запросов

Я пытаюсь выполнить поле order_by на основе m2m, но в итоге оно создает повторяющиеся записи в моем наборе запросов. Я искал документацию по django и связанные с этим вопросы по обмену стека, но я не смог найти каких-либо решений.

Модели:

class WorkOrder(models.Model):
    ...
    appointment = models.ManyToManyField(Appointment, null=True, blank=True, related_name = 'appointment_from_schedule')
    ...

class Appointment(models.Model):

    title = models.CharField(max_length=1000, blank=True)
    allDay = models.BooleanField(default=False)
    start = models.DateTimeField()
    end = models.DateTimeField(null=True, blank=True)
    url = models.URLField(blank=True, null=True)

Запрос:

qs = WorkOrder.objects.filter(work_order_status="complete").order_by("-appointment__start")

Результаты:

[<WorkOrder: 45: Davis>, <WorkOrder: 45: Davis>]

В интерактивном режиме:

>>>qs[0] == a[1]
True
>>>qs[0].pk
45
>>>qs[1].pk
45

Если я уберу order_by, то получу только один результат, но добавив его позже, я верну дубликат записи.

>>>qs = WorkOrder.objects.filter(work_order_status="complete")
>>>qs
[<WorkOrder: 45: Davis>]
>>>qs.order_by('appointment__start')
[<WorkOrder: 45: Davis>, <WorkOrder: 45: Davis>]

Я попытался добавить.distinct() и.distinct('pk'), но первый не имеет никакого эффекта, а второй приводит к ошибке:

ProgrammingError: SELECT DISTINCT ON expressions must match initial ORDER BY expressions

2 ответа

Решение

Я принял предложения sfletche по использованию annotate и обсудил эту проблему на канале frodeode.net irC#django.

Пользователи FunkyBob и jtiai смогли помочь мне заставить его работать.

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

from django.db.models import Max

WorkOrder.objects.annotate(max_date=Max('appointment__start')).filter(work_order_status="complete").order_by('max_date')

Итак, мы были на правильном пути, это было просто для получения правильного синтаксиса.

Спасибо за помощь sfletche, FunkyBob и jtiai.

Вы можете попробовать использовать annotate с values:

qs = WorkOrder.objects.filter(work_order_status="complete").values("appointment").annotate(status="work_order_status").order_by("-appointment__start")
Другие вопросы по тегам