excuse me for my ugly english) !
Imagine these very simple models :
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)
I need to select all Gallery instances which contain at least one public photo (and if possible adding a photos__count attribute which contains the number of public photos).
I tried this query :
Gallery.objects.all()\
.annotate(Count('photos'))\
.filter(photos__is_public=True)
It seems to be okay, but :
– the query is strange
– the added attribute photos__count on each gallery will contain the total number of photos on this gallery, instead of the number of public photos in this gallery.
I thin that the hard-coded sql query I need is that :
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 ;
Any idea to fix it ?
Thank you ! 😉
The django documentation is at
http://docs.djangoproject.com/en/dev/topics/db/aggregation/#order-of-annotate-and-filter-clauses
and my experience says that the following query:
would give you galleries with at least one photo that is public and a count of only photos that are public. The only thing is that it will exclude galleries with zero public photos but it sounds like you don’t care about that. Have you tested the above query?
If it still doesn’t return the right data then annotate is probably changing the returned data by causing it to return only galleries where all are public. In that case you could use the “extra” method to get the count you want.
Jason Christa’s exclude method may also work.