2

I have following 3 models

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


class Product(models.Model):

    name = models.CharField(
    blank=False,
    max_length=256
    )


class TaskGroup(models.Model):
    name = models.CharField(
    blank=False,
    max_length=256
    )

    product = models.ForeignKey(
    Product,
    on_delete=models.CASCADE,
    null=False,
    blank=True
    )


class Task(models.Model):
    name = models.CharField(
    blank=False,
    max_length=256
    )

    task_group = models.ForeignKey(
    TaskGroup,
    on_delete=models.CASCADE,
    null=False,
    blank=True
    )
    
    execute_at = models.DateField(
    blank=True
    null=True,
    )

I can order the products by Task execute_at date.

Products.objects.annotate(
    last_task=Max('taskgroup__task__execute_at')
).order_by('-last_task')

However, I need to consider only the first date that is greater than today i.e I need something like

Products.objects.annotate(
    last_task=('taskgroup__task__execute_at' >= timezone.now()).first()
).order_by('last_task')

So I need to order products by the closest Task execute_at date i.e closest to current date.

How can I do this? It would be nice to do it in a single query.

0

1 Answer 1

1

Since DJANGO 2.0 we can use the filter argument to achieve this.

The below line must be do what you want:

from django.db.models import Min, Q

Products.objects.annotate(
    last_task=Min(
        'taskgroup__task__execute_at',
        filter=Q(taskgroup__task__execute_at__gte=timezone.now()
))).order_by('last_task')
Sign up to request clarification or add additional context in comments.

8 Comments

I do not need to filter products, I need to order products by task execute_at date where execute_at date is >= timezone.now()
@StaticName, to do that first you have to do filter execute_at__gte=timezone.now(). Then you can do order_by("taskgroup__task__execute_at") for ascending or order_by("taskgroup__task__execute_at") for descending.
@zelenyjan, i think that he need first item, from the question: I need to consider only the first date that is greater than today
@StaticName, if you don't need to filter simple exclude it and use only ....order_by("-taskgroup__task__execute_at").first(). But to get items greater or equal to timezone.now() you have to do filter().
Even you do the filter, it does not work. Because at the end products are ordered by taskgroup__task__execute_at, so filter has no effect in this query.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.