Prefetch related extracted database rows?

Viewed 43

I am using this query with DRF:

def get(self, request, format=None):
        show = Show.objects.prefetch_related(
            Prefetch(
                'posttitleimage_set',
                queryset=PostTitleImage.objects.filter(post__is_published=True),
            )
        ).exclude(publication__isnull=False)[:5]

This should, however, only fetch 5 shows from the DB. Also, I'll never run into the case that I will need all posttitleimages for one show. I only ever want the latest posttitleimage for one show.

class ShowIndexSerializer(serializers.ModelSerializer):
    last_title_image = serializers.SerializerMethodField()

    class Meta:
        model = Show
        fields = (
            ....
            'last_title_image',
        )

    def get_last_title_image(self, obj):
        last_published_image = obj.posttitleimage_set.all()[: 1]
        return ShallowPostTitleImageSerializer(last_published_image, many=True).data

While my code manages to reduce the number of queries from 10 to only 4, I am now concerned about the number of rows this will query from the DB. Especially once the DB grows. Also, this seems to be a bit of a hacky solution to just get the latest posttitleimage from the DB. Are there some obvious flaws with this implementation. How could this be improved? I'd be super happy about suggestions.


EDIT:

class ShallowPostTitleImageSerializer(ModelSerializer):
    class Meta:
        model = PostTitleImage
        fields = (
            'uuid',
            'image',
            'show',
        )

Two versions of the get_last_title_image function for the Method field:

First (causes 9 queries):

def get_last_title_image(self, obj):
    published_image = obj.posttitleimage_set.first()
    return ShallowPostTitleImageSerializer(published_image).data

Second (causes only 4 queries):

def get_last_title_image(self, obj):
    published_images = obj.posttitleimage_set.all()
    if published_images:
        return ShallowPostTitleImageSerializer(published_images[len(published_images) - 1]).data
    return None
0 Answers
Related