3 回答

TA貢獻1784條經驗 獲得超9個贊
摘要:
正如jpic和sgallen在評論中所建議的那樣,一個選項是.filter()
為每個類別添加。每個附加項都會filter
添加更多聯接,這對于一小組類別來說應該不是問題。
您還可以選擇使用自定義查詢。
一些例子
測試設置:
class Photo(models.Model): tags = models.ManyToManyField('Tag')class Tag(models.Model): name = models.CharField(max_length=50) def __unicode__(self): return self.nameIn [2]: t1 = Tag.objects.create(name='holiday')In [3]: t2 = Tag.objects.create(name='summer')In [4]: p = Photo.objects.create()In [5]: p.tags.add(t1)In [6]: p.tags.add(t2)In [7]: p.tags.all()Out[7]: [<Tag: holiday>, <Tag: summer>]
使用鏈式過濾器方法:
In [8]: Photo.objects.filter(tags=t1).filter(tags=t2)Out[8]: [<Photo: Photo object>]
結果查詢:
In [17]: print Photo.objects.filter(tags=t1).filter(tags=t2).query SELECT "test_photo"."id"FROM "test_photo"INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")INNER JOIN "test_photo_tags" T4 ON ("test_photo"."id" = T4."photo_id")WHERE ("test_photo_tags"."tag_id" = 3 AND T4."tag_id" = 4 )
請注意,每個都會為查詢filter
添加更多內容JOINS
。
使用注釋 方法:
In [29]: from django.db.models import CountIn [30]: Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2)Out[30]: [<Photo: Photo object>]
結果查詢:
In [32]: print Photo.objects.filter(tags__in=[t1, t2]).annotate(num_tags=Count('tags')).filter(num_tags=2).query SELECT "test_photo"."id", COUNT("test_photo_tags"."tag_id") AS "num_tags"FROM "test_photo"LEFT OUTER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")WHERE ("test_photo_tags"."tag_id" IN (3, 4))GROUP BY "test_photo"."id", "test_photo"."id"HAVING COUNT("test_photo_tags"."tag_id") = 2
AND
ed Q
對象不起作用:
In [9]: from django.db.models import QIn [10]: Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer'))Out[10]: []In [11]: from operator import and_In [12]: Photo.objects.filter(reduce(and_, [Q(tags__name='holiday'), Q(tags__name='summer')]))Out[12]: []
結果查詢:
In [25]: print Photo.objects.filter(Q(tags__name='holiday') & Q(tags__name='summer')).query SELECT "test_photo"."id"FROM "test_photo"INNER JOIN "test_photo_tags" ON ("test_photo"."id" = "test_photo_tags"."photo_id")INNER JOIN "test_tag" ON ("test_photo_tags"."tag_id" = "test_tag"."id")WHERE ("test_tag"."name" = holiday AND "test_tag"."name" = summer )

TA貢獻1805條經驗 獲得超10個贊
另一種有效的方法,雖然只有PostgreSQL,但它正在使用django.contrib.postgres.fields.ArrayField:
從docs復制的示例:
>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])
>>> Post.objects.filter(tags__contains=['thoughts'])
<QuerySet [<Post: First post>, <Post: Second post>]>
>>> Post.objects.filter(tags__contains=['django'])
<QuerySet [<Post: First post>, <Post: Third post>]>
>>> Post.objects.filter(tags__contains=['django', 'thoughts'])
<QuerySet [<Post: First post>]>
ArrayField有一些更強大的功能,如重疊和索引轉換。

TA貢獻1829條經驗 獲得超4個贊
這也可以通過使用Django ORM和一些Python魔法的動態查詢生成來完成:)
from operator import and_from django.db.models import Q categories = ['holiday', 'summer']res = Photo.filter(reduce(and_, [Q(tags__name=c) for c in categories]))
我們的想法是為每個類別生成適當的Q對象,然后使用AND運算符將它們組合到一個QuerySet中。例如,你的例子就等于
res = Photo.filter(Q(tags__name='holiday') & Q(tags__name='summer'))
添加回答
舉報