25

Django'da iki Modelim var. Birincisi, iş fonksiyonlarının (pozisyonların) diğer pozisyonların hangi raporlarını, ikincisi ise insanların ve hangi iş işlevlerini tuttuklarının hiyerarşisine sahiptir. Bir Kişi kaydı var ve ben kişinin yöneticisini bulmak istediğinizdeGeri yabancı tuşları ile select_related

class PositionHierarchy(model.Model): 
    pcn = models.CharField(max_length=50) 
    title = models.CharField(max_length=100) 
    level = models.CharField(max_length=25) 
    report_to = models.ForeignKey('PositionHierachy', null=True) 


class Person(model.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    ... 
    position = models.ForeignKey(PositionHierarchy) 

, ben katılmak (ve bir önleyebilirsiniz, ben QuerySet insanları alıyorum Eğer

manager = person.position.report_to.person_set.all()[0] 
# Can't use .first() because we haven't upgraded to 1.6 yet 

yapmak zorunda Person.objects.select_related('position', 'position__reports_to').filter(...) kullanarak pozisyon ve report_to ile veritabanına ikinci gezi), ancak person_set almak için veritabanına başka bir gezi yapmaktan kaçınmanın herhangi bir yolu var mı? 'position__reports_to__person_set' eklemeye veya yalnızca position__reports_to__person numarasına select_related eklemeye çalıştım, ancak bu sorguyu değiştirmiyor gibi görünüyor. prefetch_related bunun için mi?

Özel bir yönetici yapmak istiyorum, böylece Kişi kayıtlarını almak için bir sorgu yaptığımda, kendi KonumHeirarchy ve yöneticilerinin Kişisel kayıtlarını veritabanına daha fazla gidiş olmadan aldım. Bu defa ne var:

class PersonWithManagerManager(models.Manager): 
    def get_query_set(self): 
     qs = super(PersonWithManagerManager, self).get_query_set() 
     return qs.select_related(
      'position', 
      'position__reports_to', 
     ).prefetch_related(
     ) 
+0

muhtemelen bir yazım hatası, ancak 'get_queryset()' değil, 'get_query_set' olmalıdır. – Paolo

+1

@Paolo, Django 1.5'te 'get_query_set' idi. –

cevap

25

Evet, bu prefetch_related() için budur. Bu, ek bir sorgu gerektirecektir, ancak fikir, tüm ilgili bilgileri bir defada Person'a bir defa yerine alacaktır. Senin durumunda

:

qs.select_related('position__report_to') 
    .prefetch_related('position__report_to__person_set') 

bakılmaksızın orijinal sorgu kümesindeki Persons sayısının, iki sorgu gerektirir gerekir.

documentation gelen bu örneği karşılaştırın:

>>> Restaurant.objects.select_related('best_pizza') 
         .prefetch_related('best_pizza__toppings')