【问题标题】:Django: retrieve all galleries containing one public photo at leastDjango:检索至少包含一张公开照片的所有画廊
【发布时间】:2009-09-02 10:38:01
【问题描述】:

对不起,我的英语很丑)!

想象一下这些非常简单的模型:

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 属性)。

我试过这个查询:

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 ;

有解决办法吗?

谢谢! ;-)

【问题讨论】:

    标签: python sql django django-models count


    【解决方案1】:

    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'))
    

    将为您提供至少一张公开照片和仅公开照片计数的画廊。唯一的问题是它将排除公共照片为零的画廊,但听起来你并不关心这一点。你测试过上面的查询吗?

    如果它仍然没有返回正确的数据,那么 annotate 可能会更改返回的数据,使其仅返回所有公开的画廊。在这种情况下,您可以使用“额外”方法来获得所需的计数。

    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 的 exclude 方法也可以工作。

    【讨论】:

    • 这有效:Gallery.objects.filter(photos__is_public=True).annotate(Count('photos')) 非常感谢(Jason 也是,您的查询有效;))。
    【解决方案2】:

    应该这样做:

    编辑、更新以添加计数:

    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 
    

    【讨论】:

    • 您的查询似乎做了两个 SELECT,而我的一个。所以我认为我的查询操作系统更加优化。 :p
    【解决方案3】:

    这个?

    Gallery.objects.filter(photos__is_public=True)\ .annotate(Count('photos__is_public'))

    【讨论】:

    • 哈,Jason 的查询集是正确且较短的,IMO。真遗憾,我在这里输入了更多的键 =],现在需要睡觉了...过滤器应用于连接的内部表的行,只有带有 is_public=Ture 的行将被留下并计算在内。
    【解决方案4】:

    我会尝试:

    Gallery.objects.filter(photos__is_public=True).annotate(Count('photos'))
    

    我相信你只是把你的过滤器排序弄错了,但我没有设置你的模型来测试这个假设。

    尝试第二个:

    Gallery.objects.exclude(photos__is_public=False).annotate(Count('photos'))
    

    这应该排除所有没有公开照片的画廊,并返回公开和不公开的数量。

    【讨论】:

    • 您好,这不起作用,因为它会选择 所有 张照片公开的画廊。但我需要选择至少一张照片是公开的画廊。此外,您的phots__count 属性将包含所有照片的数量(公开和非公开)。谢谢你同样帮助我 ;-) !
    猜你喜欢
    • 1970-01-01
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-10-03
    • 2021-10-10
    • 1970-01-01
    • 2015-03-11
    • 1970-01-01
    相关资源
    最近更新 更多