Контекстная функция шаблона Django без автоматического запуска - PullRequest
2 голосов
/ 22 февраля 2010

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

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

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> в шаблоне вместо его запуска.

1 Ответ

3 голосов
/ 22 февраля 2010

Я думаю, что вы не должны смешивать логику приложения с шаблоном (представление в шаблоне 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 }}
...