Django select_related doesn't optimize query

180 Views Asked by At

I have a problem with select_related. I don't know what I'm doing wrong but it doesn't work..

models.py

class OrganizerUser(models.Model):
    """This user manage Agents"""
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    def __str__(self):
        return self.user.username


class Agent(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    organizer = models.ForeignKey(OrganizerUser, blank=True, null=True,
                                  on_delete=models.CASCADE)

    def __str__(self):
        return self.user.username



class Lead(models.Model):
    first_name = models.CharField(max_length=20)
    last_name = models.CharField(max_length=20)
    age = models.IntegerField(default=0)
    organizer = models.ForeignKey(OrganizerUser, on_delete=models.CASCADE)
    agent = models.ForeignKey(Agent, null=True, blank=True, on_delete=models.SET_NULL)
   
    category = models.ForeignKey(
        Category, related_name="categories", null=True, blank=True,  on_delete=models.SET_NULL
    )
    description = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)
    phone_number = models.CharField(max_length=20)
    email = models.EmailField()
    converted_date = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return f"{self.first_name} {self.last_name}"

views.py

class LeadsApiView(generics.ListCreateAPIView):
    serializer_class = LeadSerializer
    permission_classes = [IsAuthenticated, IsAdminOrOrganizer]

    def get_queryset(self):
        user = self.request.user
        #if user.is_staff:
            #return Lead.objects.select_related('organizer', 'agent').all()
        if user.is_organizer:
            return Lead.objects.select_related('organizer').filter(
                organizer=user.organizeruser)
        else:
            return Lead.objects.select_related('agent').filter(agent=user.agent)

serializers.py

class LeadSerializer(serializers.ModelSerializer):
    class Meta:
        model = Lead
        fields = ['id', 'first_name', 'last_name', 'age',
                  'organizer', 'agent', 'category', 'description', 'date_added',
                  'phone_number', 'email', 'converted_date'
                  ]

for agents everything is fine. Django makes 3 queries but for other users, it makes extra queries for each existing user.

enter image description here

1

There are 1 best solutions below

0
Ryan On BEST ANSWER

This solution solved the problem How to always prefetch_related for a specific django model

class UsersManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().select_related('user')


class OrganizerUser(models.Model):
    """This user manage Agents"""
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    objects = UsersManager()

    def __str__(self):
        return self.user.username


class Agent(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    organizer = models.ForeignKey(OrganizerUser, blank=True, null=True,
                                  on_delete=models.CASCADE)
    objects = UsersManager()

    def __str__(self):
        return self.user.username