Оптимизация запроса в цикле FOR

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

n = 3
result = []
codes = Target.objects.filter(code__in=['ABC', 'CDE', ...])

for code in codes:
    result.append(Data.objects.select_related('target')
                              .filter(target__code=code)
                              .values('spec', 'spec_type')
                              .order_by('-spec')[:n])

Модели:

class Data(models.Model):
    target = models.ForeignKey(Target)
    spec_type = models.CharField()
    spec = models.FloatField()

class Target(models.Model):
    code = models.TextField(db_index=True)

Не обязательно получать codes в виде QuerySet для перечисления. Мы можем напрямую работать со списком кодов.

Если вы хотите построить QuerySet, содержащий все заданные элементы, вы можете сделать QuerySet с union, который будет извлекать эти объекты. В таком случае это можно сделать с помощью .union(…) [Django-doc]:

codes = ['ABC', 'CDE']
n = 3
result = Data.objects.none().union(
    *[
      Data.objects.filter(target__code=code).values('spec', 'spec_type').order_by('-spec')[:n]
      for code in codes
    ],
    all=True
)

Как сказал @Willem Van Onsem, вам не нужно получать queryset ваших объектов Target, поскольку у вас уже есть нужные вам коды. Просто храните коды в переменной, а затем вы можете сделать django запрос, используя этот список.

codes = ['ABC', 'CDE', ...]

result = Data.objects.filter(target__code__in = codes)

Этот запрос должен вернуть все Data объекты, код связанного Target объекта которых находится в списке codes.

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