Как использовать функцию prefetch_related() для GenericForeignKeys?

У меня есть List, состоящий из ListItems. Эти ListItems затем указывают на модель ParentItem или ChildItem через GenericForeignKey:

# models.py

class List(models.Model):
    title = models.CharField()


class ListItem(models.Model):
    list = models.ForeignKey(List, related_name="list_items")
    order = models.PositiveSmallIntegerField()

    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey("content_type", "object_id")


class ParentItem(models.Model):
    parent_title = models.CharField()


class ChildItem(models.Model):
    child_title = models.CharField()
    parent = models.ForeignKey(ParentItem, related_name="child")

Я хочу отобразить список всех моих списков с их ListItems и соответствующими данными ItemA/ItemB, используя ListSerializer:

# serializers.py

class ParentItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = ParentItem
        fields = ["parent_title"]


class ChildItemSerializer(serializers.ModelSerializer):
    parent = ParentItemSerializer()

    class Meta:
        model = ChildItem
        fields = ["child_title", "parent"]


class ListItemSerializer(serializers.ModelSerializer):
    contents = serializers.SerializerMethodField()

    class Meta:
        model = ListItem
        fields = ["contents"]

    def get_contents(self, obj):
        item = obj.content_object
        type = item.__class__.__name__
        if type == "ParentItem":
            return ParentItemSerializer(item).data
        elif type == "ChildItem":
            return ChildItemSerializer(item).data


class ListSerializer(serializers.ModelSerializer):
    items = serializers.SerializerMethodField()
    
    class Meta:
        model = List
        fields = ["title", "items"]

    def get_items(self, obj):
        return ListItemSerializer(obj.list_items, many=True).data


Как я могу оптимизировать свой набор запросов List для предварительной выборки этих отношений GenericForeignKey?

# views.py

class ListViewSet(viewset.ModelViewSet):
    queryset = List.objects.all()
    serializer_class = ListSerializer

List.objects.all().prefetch_related("list_items") работает, но следующее, похоже, не работает:

List.objects.all().prefetch_related(
    "list_items",
    "list_items__content_object",
    "list_items__content_object__parent_title",
    "list_items__content_object__child_title",
    "list_items__content_object__parent",
    "list_items__content_object__parent__parent_title",
)

Я прочитал документацию по prefetch_related, которая предполагает, что это должно работать:

Хотя prefetch_related поддерживает предварительную выборку GenericForeignKey отношения, количество запросов будет зависеть от данных. Поскольку GenericForeignKey может ссылаться на данные в нескольких таблицах, требуется один запрос на каждую таблицы, а не один запрос для всех элементов. Могут быть дополнительные запросы к таблице ContentType, если соответствующие строки еще не были извлечены.

но я не знаю, применимо ли это к DRF.

Согласно моей правке, предварительная выборка работает как положено, когда я перемещаю соответствующие поля, когда они запрашиваются в сериализаторе, вместо того, чтобы запихивать все это в кверисет представления.

Вернуться на верх