2016-09-29 2 views
0

У меня есть следующее соотношение:Как отфильтровать последние объекты с помощью вложенного запроса в Django

class Product(foo): 
    name = models.CharField() 

class Maintenance(foo): 
    product = models.ForeignKey(Product, related_name="maintenances") 
    start = models.DateField() 
    end = models.DateField() 

Я хотел бы, чтобы фильтровать все продукты с последней (только последние) содержанием объектов, имеющие start и end атрибутами в определенном диапазоне дат.

Что-то вроде этого:

Product.objects.filter(maintenances__last__end__gte=today.now(), maintenances__last__end__lte=today.now()+datetime.timedelta(days=30)) 

ответ

1

Вы можете filter продукты от выбранного диапазона дат для содержаний, а затем взять на себя обслуживание Lastest с помощью annotation на Max:

import datetime as dt 

from django.db.models import Max 

start_date = dt.datetime.now() 
end_date = dt.datetime.now() + dt.timedelta(days=30) 

products = Product.objects.filter(maintenances__start__gte=start_date, maintenances__end__lte=end_date)\ 
          .annotate(most_recent_maint=Max('maintenances__id'))\ 
          .prefetch_related('maintenances') 
1

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

# filter for time range 
maintenances = Maintenance.objects.filter(
    end__gte=today.now(), 
    end__lte=today.now() + datetime.timedelta(days=30) 
) 
# get latest with distinct product id 
maintenances = maintenances.order_by(
    'product_id', '-end' 
).distinct('product_id') 
# do a `select_related` to get all products in the same query 
maintenances = maintenances.select_related('product') 

Обратите внимание, что переданные аргументы distinct() работают только в том случае, если вы используете PostgreSQL.

+0

Но как выбрать последнюю запись обслуживания для каждой записи, которую я имею, и убедиться, что фильтр основан только на ней? Если я использую 'last_', как вы предоставили, это не сработает. Он пытается использовать его как атрибут. –

+1

Извините, просто ошибочно скопировано это ... Если я правильно понимаю ваш вопрос, он должен просто фильтровать «конец» объектов «Maintenance». Использование 'order_by' с' distinct' shoud просто дает вам последний объект для каждого 'product_id'. –

+0

Это уточняется. Благодарю. –

Смежные вопросы