2017-01-17 4 views
0

Используя GenericRelation к карте Record с до Person с, у меня есть следующий код, который работает правильно, но есть проблема с производительностью Я пытаюсь решить:Django кэширования запросов через ForeignKey на GenericRelation

models.py

class RecordX(Record): # Child class 
    .... 

class Record(models.Model): # Parent class 
    people = GenericRelation(PersonRecordMapping) 

    def people_all(self): 
     # Use select_related here to minimize the # of queries later 
     return self.people.select_related('person').all() 

    class Meta: 
     abstract = True 

class PersonRecordMapping(models.Model): 
    person = models.ForeignKey(Person) 
    content_type = models.ForeignKey(ContentType) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey('content_type', 'object_id') 

class Person(models.Model): 
    ... 

В итоге у меня есть:

RecordX ===GenericRelation===> PersonRecordMapping ===ForeignKey===> Person 

Дисплей логики в моем приложении следует эти отношения для отображения всех Person сек, отображенные на каждую RecordX:

views.py

@rendered_with('template.html') 
def show_all_recordXs(request): 
    recordXs = RecordX.objects.all() 
    return { 'recordXs': recordXs } 

Проблема возникает в шаблоне:

шаблона .html

{% for recordX in recordXs %} 
    {# Display RecordX's other fields here #} 
    <ul> 
    {% for map in record.people_all %}{# <=== This generates a query every time! #} 
     <li>{{ map.person.name }}</li> 
    {% endfor %} 
    </ul> 
{% endfor %} 

Как указано, каждый раз, когда я запрашиваю Person s, относящийся к RecordX, он генерирует новый запрос. Кажется, я не могу понять, как предварительно изначально извлекать их, чтобы избежать избыточных запросов.

Если я попробую selected_related, то я получаю сообщение об ошибке selected_related здесь могут быть здесь (сообщение об ошибке: Invalid field name(s) given in select_related: 'xxx'. Choices are: (none)). Не удивительно, теперь я вижу - на этой модели нет FK.

Если я попробую prefetch_related('people'), ошибок не будет, но я все равно получаю одинаковые повторяющиеся запросы в каждом цикле в шаблоне, как и раньше. Аналогично для prefetch_related('people__person'). Если я попробую prefetch_related('personrecordmapping'), я получаю сообщение об ошибке.

Вдоль линий this answer я рассматривал делать, пытаясь имитировать select_related через что-то вроде:

PersonRecordMapping.objects.filter(object_id__in=RecordX.objects.values_list('id', flat=True)) 

, но я не понимаю _content_object_cache достаточно хорошо, чтобы приспособить этот ответ к моей ситуации (если даже правильный подход).

Так что - как я могу заранее извлечь все Person с до RecordX с, чтобы избежать п запросов, когда страница будет отображаться пRecordX объектов?

Благодарим за помощь!

ответ

0

Ack, видимо, мне нужно было позвонить и - prefetch_related('people', 'people__person'). ВЗДОХ.