Упорядочение набора запросов на основе условия из полей в разных таблицах

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

Изначально ресурсы хранились следующим образом.

from django.db import models
from django.utils import timezone


class Entity(models.Model):
    has_subscription = models.BooleanField()
    created_at = models.DateTimeField(default=timezone.now)
    # other fields


и я бы отсортировал их следующим образом,

Entity.objects.all()order_by("-has_subscription", "-created_at")

который сработал.

Я решил перейти к другому способу хранения, который бы способствовал подписке, ограниченной по времени. Я пришел к следующему варианту.

from django.db import models
from django.utils import timezone


class Entity(models.Model):
    created_at = models.DateTimeField(default=timezone.now)

    @property
    def has_active_subscription(self):
        if (
            self.entity_subscriptions.filter(
                start_date__lte=timezone.now(), end_date__gte=timezone.now()
            ).count()
            > 0
        ):
            return True

        return False

class Subscriptions(model.Model):
    entity = models.ForeignKey(
        Entity,
        on_delete=models.CASCADE,
        related_name="entity_subscriptions",
        related_query_name="entity_subscription",
    )
    start_date = models.DateTimeField()
    end_date = models.DateTimeField()

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

После долгих поисков, следующее решение сработало для меня.

from django.db.models import Case, When, Q
from django.utils import timezone

Entity.objects.annotate(
    active_sub=Case(
        When(
            Q(
                entity_subscription__start_date__lte=timezone.now(),
                entity_subscription__end_date__gte=timezone.now(),
            ),
            then=True,
        ),
        default=False,
    )
).order_by("-active_sub", "-created_at")

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