Django:如何去除extra()方法添加的GROUP BY?

0 投票
2 回答
2533 浏览
提问于 2025-04-15 14:03

你好(请原谅我的英语不好)!

当我这样做的时候:

gallery_qs = Gallery.objects.all()\
                    .annotate(Count('photos'))\
                    .extra(select={'photo_id': 'photologue_photo.id'})

这个SQL查询是:

SELECT (photologue_photo.id) AS `photo`, `photologue_gallery`.*
FROM `photologue_gallery` 
    LEFT OUTER JOIN `photologue_gallery_photos` 
      ON (`photologue_gallery`.`id` = `photologue_gallery_photos`.`gallery_id`) 
    LEFT OUTER JOIN `photologue_photo` 
      ON (`photologue_gallery_photos`.`photo_id` = `photologue_photo`.`id`) 
GROUP BY `photologue_gallery`.`id`, photologue_photo.id 
ORDER BY `photologue_gallery`.`publication_date` DESC

问题是,extra 方法会自动在 GROUP BY 子句中添加 photologue_photo.id。我需要把它去掉,因为这会导致画廊重复,比如:

[<Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>, <Gallery: Lorem ipsum dolor sit amet>]

所以我想用 Django 来做这个查询,这可能吗?

SELECT (photologue_photo.id) AS `photo`, `photologue_gallery`.*
FROM `photologue_gallery` 
    LEFT OUTER JOIN `photologue_gallery_photos` 
      ON (`photologue_gallery`.`id` = `photologue_gallery_photos`.`gallery_id`) 
    LEFT OUTER JOIN `photologue_photo` 
      ON (`photologue_gallery_photos`.`photo_id` = `photologue_photo`.`id`) 
GROUP BY `photologue_gallery`  
ORDER BY `photologue_gallery`.`publication_date` DESC

谢谢!:)

2 个回答

0

你为什么要试着获取带有照片ID的独特画廊记录呢?因为画廊和照片ID之间是多对多的关系。从我所了解的情况来看,你的查询只会为每个画廊获取一个照片ID。

如果你真的需要这样做,我觉得你可以使用distinct()来获取独特的画廊记录(顺便说一下,你不需要在里面加“all()”)。

Gallery.objects.distinct()\
               .annotate(Count('photos'))\
               .extra(select={'photo_id': 'photologue_photo.id'})

或者你可以直接访问照片ID,

g = Gallery.objects.annotate(Count('photos'))
# Get the photo
photo = g.photos[0]
1

我觉得你其实不需要额外的操作。在Django的概念里,你在运行Django的查询集时,不需要特意挑选某些特定的列。这种逻辑可以在模板那边处理。

我假设你知道怎么把 galley_qs 从你的视图传到模板里:

# views.py
gallery_qs = Gallery.objects.all()\
                .annotate(Count('photos'))

在你的模板/html里:

{% for gallery in gallery_qs %}
    {% for photo in gallery.photos %}

    {% endfor %}
{% endfor %}

photos 是你画廊模型中的一个多对多字段。

撰写回答