Я работаю над оптимизацией моих запросов ORM. У меня есть два приложения, «app1» и «app2». Один класс 'app2' имеет внешний ключ к классу app1 следующим образом:
#app1/models.py
class C1App1(WithDateAndOwner):
def get_c2_app2(self):
res = self.c2app2_set.all()
if res.count() > 0:
return res[0]
else:
return None
#app2/models.py
class C2App2(WithDateAndOwner):
c1app1 = models.ForeignKey("app1.C1App1")
is_ok = models.BooleanField(default=False)
Теперь я отображаю C2App2 для всех экземпляров C1App1 на странице администратора:
#app1/admin.py
@admin.register(C1App1)
class C1App1Admin(admin.MyAdmin):
list_display = ("get_c2_app2")
list_select_related = ()
list_prefetch_related = ("c2app2_set",)
list_per_page = 10
prefetch_related
уменьшает этот запрос:
SELECT ••• FROM `app2_c2app2` WHERE `app2_c2app2`.`c1app1_id` = 711
Duplicated 19 times.
до:
SELECT ••• FROM `app2_c2app2` WHERE `app2_c2app2`.`c1app1_id` IN (704, 705, 706, 707, 708, 709, 710, 711, 702, 703) ORDER BY `app2_c2app2`.`id` DESC
И это нормально. Теперь, если я хочу отфильтровать запрос по атрибуту C2App2 'is_ok':
#app1/models.py
class C1App1(WithDateAndOwner):
def get_c2_app2(self):
res = self.c2app2_set.filter(is_ok=False)
if res.count() > 0:
return res[0]
else:
return None
У меня все еще есть этот предварительно выбранный запрос:
SELECT ••• FROM `c2app2_set` WHERE `app2_c2app2`.`c1app1_id` IN (704, 705, 706, 707, 708, 709, 710, 711, 702, 703) ORDER BY `app2_c2app2`.`id` DESC
но с этим дублируется для каждого отображаемого экземпляра C1App1 (10). :
SELECT ••• FROM `app2_c2app2` WHERE (`app2_c2app2`.`c1app1_id` = 711 AND `app2_c2app2`.`is_ok` = 1)
Duplicated 13 times.
На самом деле запрос также дублируется снова для 3 идентификаторов из 10 отображаемых, что приводит к этим 13 дублированным запросам. Что я могу сделать, чтобы не дублировать эти запросы? Похоже, prefetch_related здесь больше не помогает.