Фильтр по дате времени, ближайшему к данному дате

У меня есть модель, которая имеет поле datetime. Теперь, учитывая конкретное datetime - DT, мне нужно получить объект, у которого есть datetime, ближайший к DT. Возможно ли это?

Спасибо,

Ответ 1

Вы можете получить его с двумя запросами и некоторой логикой:

Идея состоит в том, чтобы найти сразу один объект и тот, который непосредственно предшествует целевому дате и вернуть один из них:

# this method is on the model manager
def get_closest_to(self, target)
    closest_greater_qs = self.filter(dt__gt=target).order_by('dt')
    closest_less_qs    = self.filter(dt__lt=target).order_by('-dt')

    try:
        try:
            closest_greater = closest_greater_qs[0]
        except IndexError:
            return closest_less_qs[0]

        try:
            closest_less = closest_less_qs[0]
        except IndexError:
            return closest_greater_qs[0]
    except IndexError:
        raise self.model.DoesNotExist("There is no closest object"
                                      " because there are no objects.")

    if closest_greater.dt - target > target - closest_less.dt:
        return closest_less
    else:
        return closest_greater

Чтобы получить это с одним запросом, вы должны отказаться от ORM к необработанному SQL.

Ответ 2

Я хотел бы завершить ответ Павла, как:

dt__gte dt__lte

следует использовать вместо

В противном случае фильтрация при предоставлении точной даты не будет работать должным образом.

Ответ 3

Просто измените ответ Павлеля на:

def get_closest_to_dt(qs, dt):
    greater = qs.filter(dt__gte=dt).order_by("dt").first()
    less = qs.filter(dt__lte=dt).order_by("-dt").first()

    if greater and less:
        return greater if abs(greater.dt - dt) < abs(less.dt - dt) else less
    else:
        return greater or less