воскресенье, 26 февраля 2012 г.

Сниппеты в django как в MODx или пишем свою middleware

Я думаю многие используют flatpages или что то похожее в своих django-проектах и многим из вас не хватало динамически генерируемых кусочков внутри страниц. Кто знаком с MODx наверное уже понял в чем дело :) Там есть очень удобные штуки внутри страницы можно вставить "метку" типа [[*snippet_name]] и она заменяется на результат выполнения кода, который лежит в т.н. сниппете.
Мною это реализовано через middleware которую я вам и представляю :

file: your_project_folder/middlewares/template_injector.py
# -*- coding: utf-8 -*-
from django.conf import settings
import re

class TemplateInjector(object):
    
    def process_response(self, request, response):
        #return if admin
        if request.get_full_path().startswith('/admin'):
            return response
                
        functions = re.findall(r'{{{(.*?)}}}', response.content)
        
        #if no template vars return response
        if len(functions) == 0:
            return response
        
        #apply funciton to every match found
        for fn in functions:
            try:
                imported = __import__(settings.TEMPLATE_INJECTOR_INCLUDES + '.' + fn)                
                result = eval('imported.' + fn + '.' + fn + '()')
                response.content = re.sub(r'{{{%s}}}' % fn, result, response.content)
                result = imported = None
            except ImportError:
                response.content = re.sub(r'{{{%s}}}' % fn, '', response.content)
            
        return response

Проверяет чтоб находились не в админке, чтоб не изменить контент при редактировании :)
Находит все кусочки текста находящиеся между {{{ и }}}
Проходит в цикле по всем найденным названиям, импортирует соответствующий им файл, выполняет ф-ю и заменяет кусочек результатом выполнения функции.
Если файл не был найден - вырезает {{{snippet_name}}} части из контента.

Пару слов о настройках: как видно в настройках мы должны прописать папку где будут храниться файлы с кодом для замены. У меня в settings.py это выглядит так:
TEMPLATE_INJECTOR_INCLUDES = 'ti_includes'

и подключаем нашу middleware там же:
MIDDLEWARE_CLASSES = (
    ...,
    'project_name.middlewares.template_injector.TemplateInjector',
)
 Теперь, в своей реализации flatpages(у меня чуть больше полей и т.д. но это не важно) при редактировании страницы добавляем для примера {{{test}}} и сохраняем страницу. Ложим в папку ti_includes (или как вы обзовете ее в настройках) файлик test.py c функцией test внутри возвращающей какой либо текстовый результат и вуаля - мы видим что при выводе на странице {{{test}}} заменено результатом работы функции. Удачи = )

Комментариев нет:

Отправить комментарий