2016-11-23 7 views
1

Ich habe diese Tabellen in einer django App:Django Filter umgekehrt foreignkey

class Order(models.Model): 
    ... 

class SubOrder1(models.Model): 
    order = models.ForeignKey(Order, blank=True, null=True) 

class SubOrder2(models.Model): 
    order = models.ForeignKey(Order, blank=True, null=True) 

... 

Wie kann ich eine Abfrage auf Bestellung schreiben, die nur die Aufträge ergibt, die mindestens eine hat SubOrder1 oder SubOrder2 verwandt? Ich brauche so etwas wie

Order.objects.filter(suborder__count__ge = 1, ...) 

Ich verwende Django = 1.9.2 und Python = 3.4.1

Antwort

2

Verwenden isnull Feld Lookup:

orders_with_suborders = Order.objects.filter(
    Q(suborder1__isnull=False) | Q(suborder2__isnull=False) 
) 
+0

Danke, das habe ich gesucht. – user2194805

+0

Dies kann zu Duplikaten führen, wenn Sie nicht 'distinct()' verwenden. – Alasdair

1

Annotate your queryset mit den Zählungen der verwandten Modelle:

from django.db.models import Count 

queryset = Order.objects.annotate(
    num_suborder1=Count('suborder1', distinct=True), 
    num_suborder2=Count('suborder2', distinct=True), 
) 

die Dokumentation sehen über combining multiple aggregations Um zu erklären, warum wir brauchen distinct=True

Dann können Sie Q verwenden, um Objekte zu filtern, bei denen eine der Zählungen zu leas ist t 1.

orders_with_suborders = queryset.filter(
    Q(num_suborder1__gte=1) | Q(num_suborder1=1__gte=1), 
) 
-1

Sie können zum SubOrder1 von Order zu bekommen.

order = Order.objects.get(pk=pk) 
suborders1 = order.suborder1_set.all() 

Dann können Sie durch den Unter iterieren:

for suborder in suborders1: 
    print (suborder) 

Hoffe, es hilft Ihnen

0

Eine Lösung würde ich gerade etwas gefunden wie:

Order.objects.filter(suborder1__id__gt = -1) 

und ich konnte Verwenden Sie das gleiche für SubOrder2. Das ist eine Lösung, aber nicht wirklich djangonisch. Gibt es eine bessere Lösung?

+0

Beachten Sie, dass doppelte Ergebnisse für jede Unterordnung erhalten können. Sie können 'distinct()' verwenden, um dies zu vermeiden. – Alasdair

+0

Wahr. Vielen Dank! . – user2194805