Фильтр не работает с prefetch_related_objects - Django

Я пытаюсь написать представление, которое предварительно получает содержимое запроса, чтобы ускорить выполнение запроса (3.5s вместо 3min при цепочке запросов).

Целью является выборка некоторых строк (Exchange_pair объектов) в зависимости от значения корневой модели в пути предварительной выборки (connection.exchange_id).

connections__wallets__currency__base_pairs
    ^                               |
    |_______________________________|
         depends on the current 
        connection's exchange_id

Вид:

@api_view(['GET'])
@permission_classes([permissions.IsAuthenticated])
def get_portfolio_view(request):
    portfolio_id = request.GET.get('id')
    
    # get portfolio + prefetch connections (and other things...)
    portfolio = Portfolio.objects.prefetch_related(
        'connections__exchange',
        'connections__wallets__currency__metadata__images'
    ).get(id=portfolio_id)

    for connection in portfolio.connections.all():
        # build filter
        pairs_queryset = ExchangePair.objects.filter(
            exchange_id=connection.exchange_id,
            quote_id__in=["825", "2781", "3408", "4687"],
            last_price__isnull=False,
        )

        # prefetch for related connection
        prefetch_related_objects(
            [connection],
            Prefetch('wallets__currency__base_pairs', queryset=pairs_queryset)
        )

    data = PortfolioSerializer(portfolio).data

    return Response(data)

Модели:

class Connection(models.Model):
    exchange = models.ForeignKey(Exchange, related_name='exchange', on_delete=models.CASCADE)

    portfolios = models.ManyToManyField(Portfolio, related_name='connections')

    # ...

class ExchangePair(models.Model):
    id = models.IntegerField(primary_key=True)  # CoinMarketCap id

    exchange = models.ForeignKey(Exchange, related_name='pairs', on_delete=models.CASCADE)

    # ...

Код работает в 90% случаев. Он не работает, когда ExchangePair находится в нескольких соединениях запроса. Django просто повторно использует префетчированные ExchangePair данные предыдущего Connection. Как мне сделать каждый префетч независимым в цикле?

Удаление повторного использования кэша в коде Django из prefetch_related_objects() (django/db/models/query.py, строка 1690) заставляет его работать. Я удаляю условие, которое проверяет, кэшируются ли объекты, так что из этого:

                if not hasattr(obj, '_prefetched_objects_cache'):
                    try:
                        obj._prefetched_objects_cache = {}
                    except (AttributeError, TypeError):
                        # ...

К этому:

            try:
                obj._prefetched_objects_cache = {}
            except (AttributeError, TypeError):
                # Must be an immutable object from

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

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