Django TEMPLATE_CONTEXT_PROCESSORS вызывается слишком много раз

Мне нужно показать некоторые статистические числа на всех страницах, поэтому я решил использовать контекстные процессоры. Но я только что понял, что моя функция вызывается от 2 до 7 раз при каждой загрузке страницы. Я делаю 4 запроса внутри функции, поэтому у меня очень низкая производительность. Каждая загрузка страницы может занять до 28 (4*7) запросов...

Я хотел бы знать, почему это происходит и что я могу сделать, чтобы избежать этого.

settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.request',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.static',
    'core.views.numbers',
)

views.py

def numeros(request):
      ...
    a=table1.objects.count()
    b=table2.objects.count()
    c=table3.objects.count()
    d=table4.objects.count()
     ...
    return {'a': a,
            'b': b,
            'c': c,
            'd': d,
            'e': e,
            'f': f,
            'g': g,
            'h': h
    }

[ОБНОВЛЕНО - Спасибо]@okm и @catherine предоставили очень хорошее и дополнительное объяснение. Оба были правильными, как сказал @okm, процессоры контекста вызывались несколько раз, потому что я использовал RequestContext более одного раза.

@ Екатерина тоже правильно. Нам нужно обратить особое внимание на то, что мы помещаем в контекстные процессоры. Я изменил свой код, и я просто отображаю статистические цифры на целевой странице.

3 ответа

Решение

Функция настройки в TEMPLATE_CONTEXT_PROCESSORS имеет преимущество, позволяющее использовать ее на всех страницах. Но имейте в виду, что даже если вы не вызывали его или не использовали его, он по-прежнему загружает запросы, потому что он напрямую вызывается из настроек. Это приведет к плохой производительности. Используйте только процессор контекста, когда вам нужно использовать его почти в каждом шаблоне, например, для пользователя или других параметров, которые не требуют больших затрат.

Процессоры контекста вызываются один за другим, когда RequestContext экземпляр инициализирован, таким образом, вы можете иметь несколько RequestContext экземпляры инициализируются. Не могли бы вы отладить их, например, используя подкласс RequestContext для печати, когда он __init__ называется?

Или вы можете вернуть ленивый объект, который задерживает его оценку до тех пор, пока он действительно не понадобится, и посмотреть, не уменьшится ли количество дублированных запросов:

def numeros(request):
    return {'a': table1.objects.count,
            'b': table2.objects.count,
            ...}

У меня была более или менее та же проблема. Итак, мы вошли в одну из функций, которая была вызвана RequestContext (из TEMPLATE_CONTEXT_PROCESSORS) и зарегистрировали трассировку, чтобы увидеть, где был получен ответ:

import traceback

logger.info(traceback.format_list(traceback.extract_stack()))

Вы также можете распечатать его, если у вас не активирован регистратор.

В моем случае это было потому, что у меня был debug_toolbar, который также вызывал RequestContext.

Другие вопросы по тегам