Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make group by having count(*) with django orm

With following model:

class Day(models.Model):
    date = models.DateField(
        unique=True,
        null=False,
        blank=False,
    )


class Reservation(models.Model):
    user = models.ForeignKey(
        User,
        null=False,
        blank=False,
        related_name='reservations',
        verbose_name=_('Utilisateur'),
    )
    day = models.ForeignKey(
        Day,
        null=False,
        blank=False,
        related_name='reservations',
    )

To get days ids where number of reservations is lower or equal 5 i do:

SELECT day_id
FROM meal_reservation
GROUP BY day_id
HAVING count(*) <= 5

But how to do it with Django ORM ?

like image 511
bux Avatar asked Nov 06 '16 18:11

bux


People also ask

How do you count in Django ORM?

Use Django's count() QuerySet method — simply append count() to the end of the appropriate QuerySet. Generate an aggregate over the QuerySet — Aggregation is when you "retrieve values that are derived by summarizing or aggregating a collection of objects." Ref: Django Aggregation Documentation.

What is Groupby in Django?

The GROUP BY statement is used to combine rows with the same values, and it is mostly used with aggrege functions like COUNT(), AVG(), SUM(), etc. Whereas, the Django ORM is an abstraction layer that allows us to work with the database by translating the python code into a SQL statement.

Why Django ORM is slow?

Django's ORM is fantastic. It's slow because it chooses to be convenient but if it needs to be fast it's just a few slight API calls away. If you're curious, check out the code on Github.


1 Answers

Read the docs about the combination of using values+annotate, this is what you need:

from django.db.models import Count

Reservation.objects.values('day').annotate(cnt=Count('id')).filter(cnt__lte=5)
like image 109
Todor Avatar answered Nov 15 '22 19:11

Todor