3

I have a displays table with 147 rows. I am not doing any heavy computation on this data set I just need to get it fast from the database. For now, the load time is 3-4 seconds. Other data comes really fast, why? Does the ListApiView work slow?

@permission_classes([AllowAny])
class DisplaysList(generics.ListAPIView):
    queryset = Displays.objects.all()
    serializer_class = serializers.DisplaySerializer



class Displays(models.Model):
    name = models.CharField(max_length=45, blank=True, null=True)
    owner = models.CharField(max_length=45, blank=True, null=True)

class GeoLocation(models.Model):
    id = models.CharField(primary_key=True, max_length=32,
                          default=generate_uuid)
    display = models.ForeignKey(
        Displays, on_delete=models.CASCADE, blank=True, null=True)
    lat = models.DecimalField(max_digits = 30, decimal_places=20, blank=True, null=True)
    lon = models.DecimalField(max_digits = 30, decimal_places=20, blank=True, null=True)

I think the issue is here, how to get efficiently geolocation?

class DisplaySerializer(serializers.ModelSerializer):
    
    geolocation = serializers.SerializerMethodField()
    
    def get_geolocation(self, obj):
        gl = GeoLocation.objects.filter(display = obj)
        gll = list(gl.values)
        return gll

    class Meta:
        model = Displays
        fields = "__all__"
        
3
  • Please show your model and serializer Commented Dec 24, 2021 at 16:12
  • try this: list(GeoLocation.objects.select_related().filter(display=obj).values()) Commented Dec 24, 2021 at 16:30
  • @Ahtisham still slow, 6 sec Commented Dec 24, 2021 at 16:31

1 Answer 1

1

Use a nested serializer so that you don't have to return the nested data via a method

class GeoLocationSerializer(serializers.ModelSerializer):

    class Meta:
        model = GeoLocation
        fields = "__all__"


class DisplaySerializer(serializers.ModelSerializer):
    
    geolocation_set = GeoLocationSerializer(many=True)

    class Meta:
        model = Displays
        fields = ["name", "owner", "geolocation_set"]

Then in your view, use prefetch_related to get the nested data in a single query. This will reduce your queries to only two

@permission_classes([AllowAny])
class DisplaysList(generics.ListAPIView):
    queryset = Displays.objects.all().prefetch_related("geolocation_set")
    serializer_class = serializers.DisplaySerializer
Sign up to request clarification or add additional context in comments.

3 Comments

@Iain Shelvington Can he not use select_related here ?
@Ahtisham I'm not sure where you would use select_related here. We are using prefetch_related to fetch the objects from a reverse relationship but there are no foreign keys relationships to use select_related on?
are you saying when we fetch relation in reverse order it becomes the case of many to one ? case display is foreign key defined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.