Предварительно выбрать связанные извлеченные строки базы данных? - PullRequest
3 голосов
/ 21 февраля 2020

Я использую этот запрос с 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]

Это, однако, должно только извлечь 5 shows из БД. Кроме того, я никогда не столкнусь с тем, что мне понадобятся все posttitleimages для одного шоу. Мне нужно только самое последнее posttitleimage для одного шоу.

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

Хотя моему коду удается сократить количество запросов с 10 до только 4, теперь меня беспокоит количество строк, которые будут запрашивать из БД. Особенно, когда БД растет. Кроме того, это, кажется, немного хакерское решение, чтобы просто получить последнюю posttitleimage из БД. Есть ли очевидные fl aws с этой реализацией. Как это можно улучшить? Я был бы очень рад предложениям.


РЕДАКТИРОВАТЬ:

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

Две версии функции get_last_title_image для поля Method:

Первый (вызывает 9 запросов) :

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

Второй (вызывает только 4 запроса):

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
...