Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

annotate is adding an extra object to my queryset

I’m using DRF. I’ve got the following code where I annotate a queryset of Company objects with an additional joined field. It seems annotate is adding an extra object to my queryset.

views.py

def get(self, request, **kwargs):
        user = request.user
        
        companies = Company.objects.all()

        print(companies)
        
        user_in_queue = When(queue__users=user, then = True)
        
        companies = Company.objects.annotate(joined=Case(
            user_in_queue, default = False
        ))
        
        print(companies)

models.py

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

class Company(models.Model):
    name = models.CharField(max_length=15, unique=True)

    def __str__(self) -> str:
        return self.name
    
class User(AbstractUser):
    def __str__(self) -> str:
        return f"{self.username}"


class Queue(models.Model):
    company = models.OneToOneField(
        Company, on_delete=models.CASCADE, related_name="queue"
    )
    users = models.ManyToManyField(User, through="QueueDetails", related_name="queues")

class QueueDetails(models.Model):
    
    queue = models.ForeignKey(
        Queue,
        related_name="queue_details",
        on_delete=models.CASCADE,
    )
    user = models.ForeignKey(
        User,
        related_name="queue_details",
        on_delete=models.CASCADE,
    )

the first print gives me

<QuerySet [<Company: kfc>, <Company: kfc>]>

With a json of

[
    {
        "name": "kfc",
        "id": 1,
    },
    {
        "name": "kfc",
        "id": 2,
    }
]

The second gives me

<QuerySet [<Company: kfc>, <Company: kfc>, <Company: kfc>]>

With a json of

[
    {
        "name": "kfc",
        "id": 1,
        "joined": null
    },
    {
        "name": "kfc",
        "id": 1,
        "joined": true
    },
    {
        "name": "kfc",
        "id": 2,
        "joined": null
    }
]

I want
a json of

[
    {
        "name": "kfc",
        "id": 1,
        "joined": true
    },
    {
        "name": "kfc",
        "id": 2,
        "joined": null
    }
]

>Solution :

You want to work with an Exists subquery [Django-doc] to prevent joining:

from django.db.models import Exists, OuterRef


def get(self, request, **kwargs):
    user = request.user
    companies = Company.objects.annotate(
        joined=Exists(
            Queue.objects.filter(company_id=OuterRef('pk'), users=request.user)
        )
    )
    # …

For the serializer, you add a joined field:

class CompanySerializer(serializers.ModelSerializer):
    joined = serializers.BooleanField()

    # …
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading