Как уменьшить количество запросов `SELECT`, которые уже уменьшены с помощью "prefetch_related()" для итерации 3 или более моделей?

У меня есть модели Country, State и City, которые связаны между собой внешними ключами, как показано ниже:

class Country(models.Model):
    name = models.CharField(max_length=20)

class State(models.Model):
    country = models.ForeignKey(Country, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)
    
class City(models.Model):
    state = models.ForeignKey(State, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)

Затем я итерирую Country и State модели с помощью prefetch_related() как показано ниже:

for country_obj in Country.objects.prefetch_related("state_set").all():
    for state_obj in country_obj.state_set.all():
        print(country_obj, state_obj)
<<<Затем выполняются 2 запроса

, как показано ниже. * Я использую PostgreSQL, и ниже показаны журналы запросов PostgreSQL, и вы можете посмотреть SELECTмой ответ , объясняющий, как включить и отключить журналы запросов на PostgreSQL:

enter image description here

Далее, я итерирую модели Country, State и City с помощью prefetch_related(), как показано ниже:

for country_obj in Country.objects.prefetch_related("state_set__city_set").all():
    for state_obj in country_obj.state_set.all():
        for city_obj in state_obj.city_set.all():
            print(country_obj, state_obj, city_obj)

Затем выполняются 3 запроса SELECT, как показано ниже:

enter image description here

Теперь, как я могу сократить 3 запроса SELECT до 2 запросов SELECT или меньше для примера выше, итерируя модели Country, State и City с помощью prefetch_related()?

Вы можете достичь этого, используя вложенные prefetch_related.

prefetch_city_qs = City.objects.all()
prefetched_city = Prefetch('state_set', to_attr='prefetched_city_set',
                            query_set=prefetch_city_qs)

join_tables_2 = [prefetched_city]
prefetch_state_qs = State.objects.prefetch_related(*join_tables_2).all()
prefetched_state = Prefetch('state_set', to_attr='prefetched_state_set',
                            query_set=prefetch_state_qs)

join_tables_1 = [prefetched_state]

countries = Country.objects.prefetch_related(*join_tables).all()

тогда при итерации вы должны получить тот же доступ с помощью циклов. как

for country in countries:
   for state in country.prefetched_state_set:
       for city in state.prefetched_city_set:
           print(city, state, country)

Прошу прощения за язык и формат, так как это мой первый ответ в stackoverflow

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