Как уменьшить количество запросов `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:
Далее, я итерирую модели 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
, как показано ниже:
Теперь, как я могу сократить 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