Django, исключить контекстный процессор в представлении - PullRequest
0 голосов
/ 01 апреля 2012

У меня есть сайт с меню. Чтобы создать меню, мне нужно несколько запросов в базе данных. Поэтому я создал контекстный процессор, чтобы сделать это во всех моих представлениях.

Некоторые из моих взглядов на самом деле являются формами. Я получаю их с помощью ajax и отображаю их в диалоговом окне jquery ui, когда мои пользователи нажимают на некоторые кнопки.

Я не могу удалить все процессоры контекста для этих довольно сложных форм, мне нужны, в частности, процессоры auth, static и il8n. Но я не хочу делать запросы к меню в базе данных для отображения этих форм.

Есть ли способ исключить контекстный процессор в представлении? Я попытался поместить переменную в «request.session» в представлении, затем удалить ее и вернуть пустой словарь в моем процессоре контекста. Но это довольно плохо и возможны проблемы с параллелизмом. Я также могу проанализировать URL в «запросе» в моем процессоре контекста и вернуть пустой словарь, но это снова звучит как хак.

Есть идеи или советы? Спасибо,

Ответы [ 4 ]

3 голосов
/ 03 апреля 2012

Это то, для чего нужны ленивые объекты Джанго.Вместо того, чтобы вычислять фактическое содержимое в процессоре контекста, вы предоставляете ленивый объект со связанной функцией;когда что-то действительно пытается использовать объект, например, в шаблоне, тогда он вызывает функцию. В этом ответе приводится пример той же проблемы.

Будьте осторожны с запоминанием, если вы используете переменную более одного раза;некоторые параметры будут вызывать функцию повторно, а некоторые сохранят результат.Вы можете посмотреть на источник , чтобы быть уверенным.Я думаю, SimpleLazyObject (как в ответе выше) делает то, что вы хотите, но я не использовал это достаточно недавно, чтобы быть уверенным.

(Ответ по запросу ....)

2 голосов
/ 01 апреля 2012

Может быть проще перестроить ваше приложение, чтобы некоторые представления выполняли этот запрос, а другие - нет. Вы можете избежать этого, вызывая многократное дублирование, написав «представление на основе классов», которое делает этот конкретный запрос к базе данных и добавляет его в контекст, а затем наследует его, когда вы хотите, чтобы новое представление сделало этот дополнительный запрос. Я бы выступил за такой подход вместо глобального контекстного процессора.

В этом примере показано, как можно добавить что-либо в контекст шаблона по умолчанию.

2 голосов
/ 01 апреля 2012

Вы можете создать подкласс RequestContext в django.template.context и переопределить его __init__ метод.Затем вы можете использовать этот измененный RequestContext в этих конкретных представлениях.__init__ из RequestContext в настоящее время выглядит следующим образом:

def __init__(self, request, dict=None, processors=None, current_app=None, use_l10n=None):
        Context.__init__(self, dict, current_app=current_app, use_l10n=use_l10n)
        if processors is None:
            processors = ()
        else:
            processors = tuple(processors)
        for processor in get_standard_processors() + processors:
            self.update(processor(request))

Здесь get_standard_processors() возвращает процессоры контекста, определенные в ваших настройках.Перед вызовом процессора контекста (последняя строка приведенного выше кода) вы можете добавить проверку, которая определяет, какие процессоры нужно использовать, а какие нужно пропустить.

1 голос
/ 18 октября 2016

Этого очень легко добиться с помощью различных шаблонизаторов.

1.Определите альтернативный (легкий) шаблонизатор в настройках вашего проекта

TEMPLATES = [
    # The default engine - a heavy one with a lot of context processors
    {
        'NAME': 'default',
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.static',

                'some_app_1.context_processors.very_heavy_cp_1',
                'some_app_2.context_processors.very_heavy_cp_2',
                'some_app_3.context_processors.very_heavy_cp_3',
            ],
            'debug': True,
        },
    },
    # Light engine - only very necessary things go here
    {
        'NAME': 'light',
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.i18n',
                'django.template.context_processors.request',
                'django.template.context_processors.media',
                'django.template.context_processors.static',
            ],
            'debug': True,
        },
    },
]

2.Как использовать движок света в ваших представлениях

some_app_1.views.py

from django.shortcuts import render_to_response
from django.template import RequestContext
from django.views.generic import View, TemplateView

Образец освещения:

class TestLightView(View):
    """Test light view."""

    template_name = 'some_app_1/test_light_view.html'

    def get(self, request):
        context = {}
        response = render_to_response(
            self.template_name,
            context,
            context_instance=RequestContext(request),
            using='light'  # Note, that we use `light` engine here
        )
        return response

Образец обычного (тяжелого) просмотра:

class TestNormalView(View):
    """Test normal view."""

    template_name = 'some_app_1/test_normal_view.html'

    def get(self, request):
        context = {}
        response = render_to_response(
            self.template_name,
            context,
            context_instance=RequestContext(request),
            using='default'  # Note, that we use `default` engine here
        )
        return response

Если вы используете TemplateView, определите template_engine свойство.

Образец облегченного просмотра:

class TestTemplateLightView(TemplateView):
    """Test template light view"""

    template_engine = 'light'  # Note, that we use `light` engine here

    # Your code goes here

Образец обычного (тяжелого) просмотра:

class TestTemplateNormalView(TemplateView):
    """Test template normal view."""

    template_engine = 'default'  # Note, that we use `default` engine here

    # Your code goes here
...