Djangoのfilter()メソッドがどのように動作するのかについて、非常に基本的で根本的なものがないと思います。次のモデルの使用関連モデル分野のDjango filter()
:
class Collection(models.Model):
pass
class Item(models.Model):
flag = models.BooleanField()
collection = models.ForeignKey(Collection)
と質問の下部に移入()関数を呼び出すことにより、供給されたデータとを、./manage.pyシェルで以下を実行してみてください。
len(Collection.objects.filter(item__flag=True))
これは、flag = Trueのアイテムを少なくとも1つ持つコレクションの数である "2"を出力するという私の期待でした。この期待は、https://docs.djangoproject.com/en/1.5/topics/db/queries/#lookups-that-span-relationshipsのドキュメントに基づいています。この例では、「この例では、名前が「Beatles Blog」のブログですべてのEntryオブジェクトが取得されます。
しかし、上記の呼び出しは実際にはflag = TrueのItemレコードの数である "6"を出力します。実際に返されるオブジェクトはCollectionオブジェクトです。同じCollectionオブジェクトを複数回返すようですが、flag = Trueの対応するItemレコードごとに1回です。これは、次のように確認できます。
queryset = Collection.objects.filter(item__flag=True)
queryset[0] == queryset[1]
これはTrueを出力します。
これは正しい動作ですか?もしそうなら、根拠は何ですか?予想されるものであれば、ドキュメントは厳密に正しいと解釈することができますが、各オブジェクトを複数回返すことができるとは言いません。
これは、非常に驚くべき(またはまったく間違った)動作であるように見える関連する例です。 )これは、除外()コールは、カスタムモデルマネージャによって追加された場合には私を捕まえて、発信者は、次いで、(フィルタを追加した
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"))]
第一ケースプリント「[2,4]」しかし、2枚目に "[8,16]"という文字が印刷されます。
移入機能:
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()