wasp256
wasp256

Reputation: 6242

Django group by add non existing choices

I have a model field that contains choices:

 db_redirection_choices = (('A', 'first'), ('B', 'second'))     

 redirection_type = models.CharField(max_length=256, choices=db_redirection_choices, blank=True, null=True)

At some point I'm performing a group by on that column, counting all existing choices:

results = stats.values('redirection_type').annotate(amount=Count('redirection_type')).order_by('redirection_type')

However, this will give me only results for existings choices. I'd like to add the ones that are not even present with 0 to the results

e.g. If the table contains only the entry

 Id   |   redirection_type
 --------------------------
  1   |    'A'

then the annotate will return only

 'A': 1

of course that's normal, but I'd still like to get all non-existing choices in the results:

 {'A': 1, 'B': 0}

What's the easiest way of accomplishing this?

Upvotes: 0

Views: 23

Answers (1)

Bruno A.
Bruno A.

Reputation: 1875

I don't think there is an easy way to do it with the ORM, except maybe using a conditional expression, but that would make your query a lot more complicated, I think.

Why not do a simple post-processing in Python?

db_redirection_choices = (('A', 'first'), ('B', 'second'))
# I think your queryset will have a similar shape
results = [{'redirection_type': 'A', 'amount': 1}]
results_map = {
    **{choice: 0 for choice, _display in db_redirection_choices},
    **{res['redirection_type']: res['amount'] for res in results}
}
assert results_map == {'A': 1, 'B': 0}

If you don't need further processing in the ORM, that seems like the easiest.

Upvotes: 1

Related Questions