Django - Фильтр одного и того же значения с несколькими датами

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

class Parcel(models.Model):
    """ Class designed to create parcels. """
    name = models.CharField(max_length=255, blank=True, null=True)
    tracking_number = models.CharField(max_length=255, blank=True, null=True)
    description = models.TextField(blank=True, null=True)

class ParcelStatus(models.Model):
    """ Class designed to create parcel status. """

    SLA_choices = (
        (_('Parcel shipped'), 'Parcel shipped'),
        (_('Delivered'), 'Delivered'),
        (_('In transit'), 'In transit'),
        (_('Exception A'), 'Exception A'),
        (_('Exception B'), 'Exception B'),
        (_('Exception C'), 'Exception C'),
        (_('Other'), 'Other'),
        (_('Claim'), 'Claim'),
    )

    parcel = models.ForeignKey(Parcel, on_delete=models.CASCADE, blank=False, null=True)
    status = models.CharField(max_length=255, blank=True, null=True, choices=SLA_choices)
    event = models.ForeignKey(GridEventTransporter, on_delete=DO_NOTHING, blank=True, null=True)
    reason = models.ForeignKey(GridReasonTransporter, on_delete=DO_NOTHING, blank=True, null=True)
    date = models.DateTimeField(blank=True, null=True)

Я получаю несколько статусов для одной посылки. Например:

Parcel Status Date
XXXX Delivered 2022-22-12 13:00
XXXX Delivered 2022-15-12 18:20
XXXX Delivered 2022-12-12 15:27
XXXX Delivered 2022-12-12 15:21
XXXX In transit 2022-12-12 03:21

Внутри моего класса я извлекаю такие посылки, как:

    def get_parcels(self):
        return Parcel.objects.filter(company=self.company)

    def get_parcels_delivered(self):
        parcels = self.get_parcels()
        parcels = parcels.filter(parcelstatus__status='Delivered', parcelstatus__date__date=self.date)
        parcels = parcels.distinct()
        return parcels

Моя проблема заключается в следующем: как вы можете видеть, я получаю несколько статусов Delivered с разными датами. Я хотел бы получить только посылку с датой 2022-12-12 15:21. В моем приложении, если я фильтрую с помощью формы даты, посылка будет показана на 2022-12-12, 2022-12-15 и 2022-12-22. Если я выбираю 2022-12-15 или 22, я не хочу, чтобы посылка была показана. В принципе, я хочу, чтобы посылка отображалась только в том случае, если первая дата появления Delivered совпадает с датой, которую я выбрал. У вас есть идеи, как мне нужно модифицировать фильтр?

Вы можете попробовать следующее:

parcels = parcels.filter(parcelstatus__status='Delivered', 
parcelstatus__date__date=self.date).earliest('date')

Согласно документации, он должен получить самый ранний объект с указанной вами датой.
Doc: https://docs.djangoproject.com/en/4.2/ref/models/querysets/#earliest

Вы можете попробовать следующим образом, используя Subquery:

from django.db.models import OuterRef, Subquery

def get_parcels_delivered(self):
    parcels = self.get_parcels()
    query= ParcelStatus.objects.filter(parcel_id=OuterRef('pk'), status='Delivered').order_by('date')
    parcels = parcels.filter(parcelstatus__status='Delivered').annotate(parcel_delivery_date=Subquery(query.values('date')[:1])).filter(parcel_delivery_date__date=self.date)
    return parcels

Здесь я аннотирую самую раннюю дату объекта ParcelStatus набором запросов Parcel, а затем фильтрую по ней.

Вернуться на верх