Контекстный процессор с использованием Werkzeug и Jinja2 - PullRequest
4 голосов
/ 12 февраля 2009

Мое приложение работает на App Engine и реализовано с использованием Werkzeug и Jinja2 . Мне бы хотелось иметь что-то функционально эквивалентное собственному контекстному процессору Django: вызываемое, которое принимает запрос и добавляет что-то в контекст шаблона. У меня уже есть «контекстные процессоры», которые добавляют что-то к контексту шаблона, но как мне заставить работать эту request часть? Я реализовал контекстные процессоры как вызываемые, которые просто возвращают словарь, который позже используется для обновления контекста.

Например, я хотел бы добавить что-то, что содержится в request.environ.

Ответы [ 2 ]

4 голосов
/ 12 февраля 2009

Одним из способов достижения этого является использование глобальных шаблонов с поздним связыванием с использованием локального прокси-потока в Werkzeug.

Простой пример, который помещает запрос в глобальные переменные шаблона:

from werkzeug import Local, LocalManager
local = Local()
local_manager = LocalManager([local])

from jinja2 import Environment, FileSystemLoader

# Create a global dict using the local's proxy to the request attribute
global_dict = {'request': local('request')}
jinja2_env = Environment(loader=FileSystemLoader('/'))
jinja2_env.globals.update(global_dict)

def application(environ, start_response):
    """A WSGI Application"""
    # later, bind the actual attribute to the local object
    local.request = request = Request(environ)

    # continue to view handling code
    # ...

application = local_manager.make_middleware(application)

Теперь в любом из ваших шаблонов текущий запрос будет связан с переменной «запрос». Конечно, это может быть что-то еще в окружающей среде. Хитрость заключается в том, чтобы использовать локальный прокси-сервер, а затем установить значение, прежде чем создавать какой-либо шаблон.

Вероятно, мне следует добавить, что фреймворк, такой как Glashammer (Werkzeug + Jinja2), упрощает этот процесс для вас, используя события. Многие функции могут подключаться к событиям во время процесса вызова WSGI (например, при создании запроса), и они могут помещать вещи в пространство имен шаблона в этот момент.

3 голосов
/ 19 февраля 2009

Ну, используя то, что написал Али Я пришел к решению, специфичному для App Engine (из-за его кэша импорта). К сожалению, код Али не работает с App Engine, потому что код, который устанавливает глобальные переменные Jinja, импортируется только один раз (что делает глобальные переменные фактически статическими). ​​

Я должен был написать свою собственную функцию render() и обновить там контекст. Для полноты ниже приведен код, к которому я пришел:

def render(template, **kwargs):
    response_code = kwargs.pop('response_code', 200)
    mimetype = kwargs.pop('mimetype', 'text/html')
    for item in getattr(settings, 'CONTEXT_PROCESSORS', []):
        try:
            processor = import_string(item)
            kwargs.update(processor(local.request))
        except (ImportError, AttributeError), e:
            logging.error(e)
    return Response(jinja_env.get_template(template).render(**kwargs),
        status=response_code, mimetype=mimetype)

Это специфично для App Engine. В других средах код Али работает, как и ожидалось (и именно поэтому я поменяю свой вопрос).

...