I have the following models:
class Foo(models.Model):
pass
class Bar(models.Model):
foo = models.ForeignKey(Foo)
is_successful = models.BooleanField()
I would like to get all foo
objects with an annotation if all of the bar
objects associated with foo
object have is_successful
as True
So far my queryset is:
foos = Foo.objects.all().annotate(all_successful=Min('bar__is_successful'))
The idea for the all_successful
annotation is that if the minimum value of all is_successful
rows is 1, then all of them must be True
(assuming 0
is False
and 1
is True
). So knowing that I can use the queryset like so:
foo = foos[0]
if foo.all_successful == 1:
print 'All bars are successful'
else:
print 'Not all bars are successful'
This works great in sqlite however it fails in PostgreSQL because PostgreSQL can't execute MIN
aggregate on a boolean column. I guess this works in sqlite because sqlite treats bools as integers hence it can execute the aggregate.
My question is how can I make this queryset work in PostgreSQL without converting my is_successful
field to an IntegerField
?
Thanx
being inspired by https://docs.djangoproject.com/en/dev/topics/db/managers/ I suggest to use a custom manager for Bar class instead of annotation
then, in your code:
FOR DJANGO <= 1.7: to get an
annotation
I think you can simply use Extraif your system is running Django 1.8+ please follow Dav3xor answer.
I know this is an old question, but I ran up against this recently. Django v1.8 now has built in support for case/when, so you can use the ORM instead of hacking around with custom SQL.
https://docs.djangoproject.com/en/1.8/ref/models/conditional-expressions/#case
I haven't tried this out, but something similar worked for me on a recent project.