2016-09-29 2 views
0

Ich habe die folgende Beziehung:Wie neueste Objekte mit verschachtelter Abfrage in Django filtern

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

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

Ich möchte alle Produkte mit den neuesten filtern (nur der letzten) Objektpflege mit start und end Attributen in einem bestimmten Zeitraum.

Etwas wie folgt aus:

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

Antwort

1

Sie könnten die Produkte auf dem gewählten Zeitraum für Instandhaltungen filter und dann die Verwendung von annotation auf Maxneuesten Wartung nehmen:

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

In einigen Es kann auch sinnvoll sein, umgekehrt zu denken: Wählen Sie für jedes Produkt das neueste Objekt 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') 

Beachten Sie, dass das Übergeben von Argumenten an distinct() nur funktioniert, wenn Sie PostgreSQL verwenden.

+0

Aber wie wähle ich den neuesten Wartungsdatensatz für jeden Eintrag, den ich habe, und stelle sicher, dass der Filter nur darauf basiert? Wenn ich 'last_' benutze, funktioniert es nicht. Es versucht, es als Attribut zu verwenden. –

+1

Tut mir leid, ich habe es einfach falsch kopiert ... Wenn ich Ihre Frage richtig verstanden habe, sollte sie nur nach 'Ende' der' Maintenance' Objekte filtern. Verwenden Sie 'order_by' mit' distinct' und geben Sie nur das neueste Objekt für jede 'product_id' an. –

+0

Das verdeutlicht. Vielen Dank. –

Verwandte Themen