Ich glaube, ich bin fehlt etwas sehr einfach und grundlegend wie Djangos filter() Methode arbeiten soll.Django filter() auf dem Feld von verwandten Modell
Verwendung der folgenden Modelle:
class Collection(models.Model):
pass
class Item(models.Model):
flag = models.BooleanField()
collection = models.ForeignKey(Collection)
und mit Daten versorgt, indem die Populate() -Funktion an der Unterseite der Frage zu stellen, versuchen, die folgenden in ./manage.py Shell ausführt:
len(Collection.objects.filter(item__flag=True))
war meine Erwartung, dass diese „2“ drucken würde, was die Anzahl der Kollektionen ist, dass mindestens ein Element mit Flag haben = True. Diese Erwartung wurde bei https://docs.djangoproject.com/en/1.5/topics/db/queries/#lookups-that-span-relationships auf der Dokumentation basiert, die ein Beispiel hat sagen: „In diesem Beispiel werden alle Eingabeobjekte mit einem Blog, dessen Name‚Beatles Blog‘“.
jedoch oberhalb der Anruf druckt tatsächlich „6“, die die Anzahl der Artikeldatensätzen ist, die Flagge haben = True. Die tatsächlichen Objekte, die zurückgegeben werden, sind jedoch Auflistungsobjekte. Es scheint, dass es das gleiche Collection-Objekt mehrmals zurückgibt, einmal für jeden entsprechenden Item-Datensatz mit Flag = True. Dies kann bestätigt werden durch:
queryset = Collection.objects.filter(item__flag=True)
queryset[0] == queryset[1]
die True druckt.
Ist das das richtige Verhalten? Wenn ja, was ist der Grund? Wenn es das ist, was erwartet wird, könnte die Dokumentation als streng korrekt interpretiert werden, aber es lässt sich nicht sagen, dass jedes Objekt mehrfach zurückgegeben werden kann.
Hier ist ein ähnliches Beispiel, das sehr überraschend zu sein scheint (oder falsch nur plain) Verhalten. Es fing mich in einem Fall, wo ein auszuschließen sind() Aufruf von einem Manager benutzerdefinierte Modell hinzugefügt wurde und der Anrufer wurde dann das Hinzufügen eines Filters():
from django.db.models import Count
[coll.count for coll in Collection.objects.filter(item__flag=True).annotate(count=Count("item"))]
[coll.count for coll in Collection.objects.exclude(item=None).filter(item__flag=True).annotate(count=Count("item"))]
ersten Fall druckt „[2,4]“ , aber der zweite druckt "[8,16]" !!!
Populate Funktion:
def populate():
Collection.objects.all().delete()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()