2016-09-24 2 views
0

В моем проекте django у меня есть 3 модели, упрощенные для этого примера: Contact, WorkRelation и Group objects.Оптимизация запросов в Django, prefact_related для объектов, которые имеют обратную связь

Контакт

class Contact(BaseModel): 
    title = models.CharField(max_length=30, blank=True) 
    initials = models.CharField(max_length=10, blank=True) 
    first_name = models.CharField(max_length=30, blank=True) 
    prefix = models.CharField(max_length=20, blank=True) 
    surname = models.CharField(max_length=30) 

    def get_workrelations(self): 
     workrelations = apps.get_model('groups', 'WorkRelation') 
     return workrelations.objects.filter(contact=self) 

    def get_organisations(self): 
     output = "" 
     strings = [] 
     wr = self.get_workrelations() 
     for relation in wr: 
      group = relation.group 
      name = group.name 
      strings.append(s) 
     if len(strings) > 0: 
      output = ", ".join(strings) 
     return output 

WorkRelation

class WorkRelation(BaseModel): 
    contact = models.ForeignKey(Contact, on_delete=models.CASCADE) 
    group = models.ForeignKey(Group, on_delete=models.CASCADE) 
    function = models.CharField(max_length=40, blank=True) 
    email_address = models.EmailField() 
    phone_number = models.CharField(max_length=13, blank=True) 
    description = models.TextField(max_length=400, blank=True) 

Группа

class Group(BaseModel): 
    group_type = models.ForeignKey(GroupType, on_delete=models.CASCADE) 
    name = models.CharField(max_length=60, unique=True) 
    street_name = models.CharField(max_length=40, blank=True) 
    house_number = models.CharField(max_length=10, blank=True) 

Проблема с этой установкой я что он становится очень медленным, когда я хочу вызвать get_organisations() на большой набор контактов. Например: при попытке перечислить все мои контакты (600 для моего демонстрационного набора) и вызвать get_organisations() требуется около 1250 запросов.

Я обнаружил, что вы можете предотвратить это, используя prefetch_data(), но каким-то образом я не могу заставить это работать в моей настройке. Я попытался заменить мой запрос на

queryset = Contact.objects.prefetch_related('workrelation_set') 

Но это не ускорило (против моей презумпции). Вы, ребята, знаете, можно ли даже ускорить это?

ответ

1

Изменить get_organisations код этого:

def get_organisations(self): 
    return ', '.join(
     workrelation.group.name for workrelation 
     in self.workrelation_set.all() 
    ) 

И использовать этот запрос для извлечения объектов Контакты:

Contact.objects.prefetch_related('workrelation_set__group') 

Это будет возвращать результат с помощью одного запроса.

+0

Ничего себе, вы не представляете, как долго я искал это. Благодаря! – hY8vVpf3tyR57Xib