В моей компании есть довольно сложная сеть Django моделей, с которыми я не особо разбираюсь. Но иногда мне нужно делать запросы на это. То, что я делаю сейчас, занимает слишком много времени. Так как я не совсем понимаю, как эффективно использовать аннотации, и я совсем не разбираюсь в подзапросах (и, возможно, в некоторых других ключевых вещах Django), я надеялся, что кто-то здесь сможет помочь понять, как сделать лучше работа по получению этого результата быстрее.
Вот факсимиле соответствующих моделей в нашей базе данных.
class Company(models.Model):
name = models.CharField(max_length=255)
@property
def active_humans(self):
if hasattr(self, '_active_humans'):
return self._active_humans
else:
self._active_humans = Human.objects.filter(active=True, departments__company=self).distinct()
return self._active_humans
class Department(models.Model):
name = models.CharField(max_length=225)
company = models.ForeignKey(
'muh_project.Company',
related_name="departments",
on_delete=models.PROTECT
)
humans = models.ManyToManyField('muh_project.Human', through='muh_project.Job', related_name='departments')
class Job(models.Model):
name = models.CharField(max_length=225)
department = models.ForeignKey(
'muh_project.Department',
on_delete=models.PROTECT
)
human = models.ForeignKey(
'muh_project.Human',
on_delete=models.PROTECT
)
class Human(models.Model):
active = models.BooleanField(default=True)
@property
def fixed_happy_dogs(self):
return self.solutions.filter(is_neutered_spayed=True, disposition="happy")
class Dog(models.Model):
is_neutered_spayed = models.BooleanField(default=True)
disposition = models.CharField(max_length=225)
age = models.IntegerField()
human = models.ForeignKey(
'muh_project.Human',
related_name="dogs",
on_delete=models.PROTECT
)
human_job = models.ForeignKey(
'muh_project.Job',
blank=True,
null=True,
on_delete=models.PROTECT
)
Что я пытаюсь сделать (на языке этого примера глупой игрушки) чтобы получить количество людей с по крайней мере одним из определенного типа собаки для каждой из некоторых компаний. Итак, что я делаю, так это запускаю.
rows = []
company_type = "Tech"
fixed_happy_dogs = Dog.objects.filter(is_neutered_spayed=True, disposition="happy")
old_dogs = fixed_happy_dogs.filter(age__gte=7)
companies = Company.objects.filter(name__icontains=company_type)
for company in companies.order_by('id'):
humans = company.active_humans
num_humans = humans.distinct().count()
humans_with_fixed_happy_dogs = humans.filter(dogs__in=fixed_happy_dogs).distinct().count()
humans_with_old_dogs = humans.filter(dogs__in=old_dogs).distinct().count()
rows.append(f'{company.id};{num_humans};{humans_with_fixed_happy_dogs};{humans_with_old_dogs}')
Обычно запуск занимает от 45 до 120 секунд в зависимости от того, сколько компаний я им управляю. Я хотел бы сократить это. Мне нужен конечный результат в виде списка строк, как показано.