Трябва да извличам данни от множество таблици с динамично изграден филтър, който може да не използва данни от някоя от таблиците.
Така казвам, че имам това:
class Solution(models.Model):
name = models.CharField(max_length=MAX, unique=True)
# Other data
class ExportTrackingRecord(models.Model):
tracked_id = models.IntegerField()
solution = models.ForeignKey(Solution)
# Other data
Тогава другаде трябва да направя:
def get_data(user_provided_criteria):
etr = ExportTrackingRecord.objects.filter(make_Q_object(user_provided_criteria)).select_related()
for data in etr:
s = data.solution
# do things with data from both tables
Доколкото мога да кажа, ако се случи да филтрирам в поле в Solution, django ще направи присъединяването и select_related
вземете и двата обекта. Ако филтрирам само полета в ExportTrackingRecord
след това няма да има присъединяване и django ще генерира нова заявка за всеки ExportTrackingRecord
в QuerySet (което може да бъде хиляди ...)
Аз съм доста нов в django, но има ли разумен начин да принудиш присъединяването?
Отговори:
1 за отговор № 1select_related()
е ключът към проблема ви. Ако не го използвате и не филтрирате в полетата на съответния модел, Django няма да направи връзка и ще предизвика допълнително запитване за всеки ред в резултата, ако имате достъп до данни от свързания модел.
Ако направите нещо подобно ExportTrackingRecord.objects.filter(...).select_related("solution")
принуждаваш Django винаги да се присъедини към Solution
таблица.
Ако трябва да направите същото и в другата посока, чрез обратния външен ключ, който ви е необходим prefetch_related()
, същото за много-към-много отношения
0 за отговор № 2
select_related
контролира това, което се зарежда в резултатите, когато се оценява QuerySet. ще принуди присъединяването независимо от филтрирането.
Ако не посочите select_related
, дори и ако вашият филтър генерира SQL заявка с присъединяване, полетата на родителския модел няма да бъдат заредени в резултатите и достъпът до тях ще изисква допълнителни заявки.