Функция контекста шаблона Django без автоматического запуска

Извините или запутанный заголовок! На самом деле это намного проще, чем кажется.

У меня есть функция:

def get_messages(request):
    # do something expensive with the request
    return 'string'

Я хочу иметь возможность вызывать эту функцию из шаблона, поэтому я привязался к обработчику контекста:

def context_processor(request):
    return {'messages':get_messages(request)}

Так что теперь, когда у меня есть {{messages}} в моем шаблоне, string распечатывается. Большой.

Проблема в том, что get_messages довольно дорог и не всегда нужен. Менее половины шаблонов нуждаются в этом. Есть ли способ передать функцию шаблону и оставить ее на усмотрение шаблона, если он запустится или нет?

Я пробовал это уже:

def context_processor(request):
    return {'messages':get_messages}

Но это просто выводит описание функции <function get_messages at 0x23e97d0> в шаблоне, а не запускает его.


person Oli    schedule 22.02.2010    source источник


Ответы (1)


Я думаю, что вы не должны смешивать логику приложения с шаблоном (представление в шаблоне MVC). Это нарушает согласованность архитектуры. Вы можете вызвать get_messages в представлениях, которым это необходимо, и просто передать messages в контекст шаблона, в остальных просто передать None.

Но отвечая на Ваш вопрос: Вы можете сделать прокси-объект. Например:

class Proxy(object):
    def __init__(self, request)
        self.request = request
        super(Proxy, self).__init__()

    def get_messages(self):
        # so some expensive things
        return 'string'

# context processor
def context_processor(request):
    return {'messages':Proxy(request)}

# in the view
{{ messages.get_messages }}

Вы можете сделать это еще более универсальным и создать класс Proxy, который имеет один метод (например, get) и принимает один параметр в конструкторе: функцию, которая принимает объект запроса в качестве первого параметра. Таким образом, вы получаете общий метод для проксирования вызова функции в ваших шаблонах. Вот:

class Proxy(object):
    def __init__(self, request, function)
        self.request = request
        self.function = function
        super(Proxy, self).__init__()

    def get(self):
        return self.function(self.request)

то Вы можете написать еще круче, чем я писал до этого:

# context processor
def context_processor(request):
    return {'messages':Proxy(request, get_messages)}

# sounds nice to me
{{ messages.get }}
person Dawid    schedule 22.02.2010
comment
Это решение только что пришло мне в голову снаружи, когда я задумчиво курил сигарету. Не то чтобы я приписываю себе заслуги, просто говорю: я полностью согласен; это похоже на лучшее доступное решение! - person Oli; 22.02.2010