请原谅我丑陋的英语!)
想象一下这些非常简单的模型:
class Photo(models.Model):
is_public = models.BooleanField('Public', default=False)
class Gallery(models.Model):
photos = models.ManyToManyField('Photos', related_name='galleries', null=True, blank=True)
我需要选择包含至少一张公共照片的所有Gallery
个实例(如果可能的话,添加包含公开照片数量的photos__count
属性)。< / p>
我尝试了这个查询:
Gallery.objects.all()\
.annotate(Count('photos'))\
.filter(photos__is_public=True)
似乎没关系,但是:
- 查询很奇怪
- 每个图库中添加的属性photos__count
将包含此图库中的照片总数,而不是此图库中公开照片的数量。
我认为我需要的硬编码sql查询是:
SELECT `gallery`.* , COUNT(`gallery_photos`.`photo_id`)
FROM `gallery`
INNER JOIN `gallery_photos` ON (`gallery`.`id` = `gallery_photos`.`gallery_id`)
INNER JOIN `photo` ON (`gallery_photos`.`photo_id` = `photo`.`id`)
WHERE `photo`.`is_public` = True
GROUP BY gallery.id ;
有什么想法来解决它吗?
谢谢! ; - )
答案 0 :(得分:0)
这应该这样做:
修改,更新以添加计数:
SELECT `gallery`.*, 'a'.'count'
FROM `gallery`
inner join (
select `gallery`.`id`, count(*) as count
from `gallery_photos`
INNER JOIN `photo` ON (`gallery_photos`.`photo_id` = `photo`.`id`)
where `photo`.`is_public` = True
group by `gallery`.`id`
) a on `gallery`.`id` = 'a'.'id'
WHERE `photo`.`is_public` = True
答案 1 :(得分:0)
我会尝试:
Gallery.objects.filter(photos__is_public=True).annotate(Count('photos'))
我相信你的过滤器排序错误,但我没有设置你的模型来测试这个假设。
尝试第二个:
Gallery.objects.exclude(photos__is_public=False).annotate(Count('photos'))
这应该排除所有照片都没有公开的所有画廊,并返回一个是什么和不公开的数量。
答案 2 :(得分:0)
此?
Gallery.objects.filter(photos__is_public=True)\ .annotate(Count('photos__is_public'))
答案 3 :(得分:0)
django文档位于
http://docs.djangoproject.com/en/dev/topics/db/aggregation/#order-of-annotate-and-filter-clauses
我的经验说明了以下问题:
Gallery.objects.filter(photos__is_public=True).annotate(Count('photos'))
会为您的图库提供至少一张公开的照片以及仅公开的照片。唯一的问题是它会排除没有公开照片的画廊,但听起来你并不关心这一点。你测试了上面的查询吗?
如果它仍然没有返回正确的数据,那么注释可能会改变返回的数据,因为它只返回所有公共的画廊。在这种情况下,您可以使用“额外”方法来获得所需的计数。
Gallery.objects.filter(photos__is_public=True).extra(select={
"photo_count": """
SELECT COUNT(`gallery_photos.id`)
FROM `gallery_photos`
WHERE `gallery_photos.gallery_id` `gallery.id AND
`gallery_photos.is_public = True
"""})
Jason Christa的排除方法也可行。