2011-12-22 3 views
8

저는 개발을 위해 Bottle.py 및 Google App Engine의 dev_appserver와 함께 Jinja2 템플릿을 사용하고 있습니다. 템플릿이 자동으로 모든 요청에 ​​대해 다시로드되도록 (또는 이상적으로는 변경 될 때만) 템플릿을 사용하여 서버를 다시 시작하지 않아도됩니다.bottle.py에서 Jinja2 템플릿 캐싱을 비활성화하는 가장 좋은 방법은 무엇입니까?

병의 문서에 따르면 bottle.debug(True)을 호출하여 템플릿 캐싱을 사용 중지 할 수 있다고 가정합니다.

그래도 Jinja는 템플릿을 캐싱하는 것처럼 보입니다. 병 jinja2 어댑터가 쓰여진 방식 (기본 Jinja2 로더를 사용하고 많은 구성 옵션을 노출하지 않음) 때문에 이것이라고 생각합니다. Jinja2 Docs 다음

는, 내가 템플릿 때마다 다시로드 트리거 예상이 사용자 정의 로더를 작성하지만 중 하나가 작동하지 않는 것 :

이 이
import settings 
from bottle import jinja2_template 
from bottle import Jinja2Template, template as base_template 
class AutoreloadJinja2Template(Jinja2Template): 
    def loader(self, name): 
     def uptodate(): 
      # Always reload the template if we're in DEVMODE (a boolean flag) 
      return not settings.DEVMODE 
     fname = self.search(name, self.lookup) 
     if fname: 
      with open(fname, "rb") as f: 
       source = f.read().decode(self.encoding) 
      return (source, fname, uptodate) 


template = functools.partial(base_template, 
    template_adapter=AutoreloadJinja2Template, 
    template_lookup = settings.TEMPLATE_PATHS, 
    template_settings={ 
     'auto_reload': settings.DEVMODE 
    } 
) 

템플릿은 여전히 ​​캐시지고 내가 다시 시작할 때까지 dev_appserver. 이것은 상당히 일반적인 문제 여야합니다. 누구든지 작동하는 솔루션이 있습니까?

UPDATE :

내가 좋아하는 뭔가를하고 결국은 :

class CustomJinja2Template(Jinja2Template): 
    if settings.DEVMODE: 
     def prepare(self, *args, **kwargs): 
      kwargs.update({'cache_size':0}) 
      return Jinja2Template.prepare(self, *args, **kwargs) 

template = functools.partial(original_template, template_adapter=CustomJinja2Template) 

이 항상 다시로드 템플릿을 유발하지만, 파이썬 모듈이 접촉 된 경우에만. 즉, 템플릿 파일을 편집하는 경우 변경 사항은 가져 오는 파이썬 파일 중 하나를 편집 할 때까지 영향을 미치지 않습니다. 마치 템플리트가 여전히 어딘가에 캐시되고있는 것 같습니다.

답변

6

병의 템플릿 솔루션을 완전히 버리고 순수 jinja2를 사용하여이 문제를 해결했습니다. Jijnja의 FileSystemLoader만이 파일 변경 사항을 볼 수있는 것으로 보입니다.

from jinja2 import Environment, FileSystemLoader 

if local_settings.DEBUG: 
    jinja2_env = Environment(loader=FileSystemLoader('views/'), cache_size=0) 
else: 
    jinja2_env = Environment(loader=FileSystemLoader('views/')) 

def template(name, ctx): 
    t = jinja2_env.get_template(name) 
    return t.render(**ctx) 

가 그럼 난 이렇게 사용 :

@route('/hello') 
def hello(): 
    return template('index.tpl', {'text': "hello"}) 

의 차이 (그냥 사용 병처럼 views/에서 파일을 찾습니다) 다음과 같이

나는 새로운 template 기능을 정의 병의 API는 파일 이름에 .tpl을 포함해야하고 사전으로 컨텍스트 변수를 전달해야한다는 것입니다.

3

jinja2의 Environment 객체는

If the cache size is set to 0 templates are recompiled all the time

당신이 이런 식으로 뭔가를 시도, 문서에 따라, 캐시 크기에 대한 구성 값을 가지고?

from jinja2 import Environment 
env = Environment(cache_size=0) 
1

병보기 데코레이터를 사용하면 @view('your_view', cache_size=0)을 사용할 수 있습니다.

병에는 서버 어댑터에 reloader=True 매개 변수가 있지만 SimpleTemplate에서만 작동합니다. 이 동작을 다른 템플릿 엔진으로 확장하려고합니다. 당신은 모든 뷰에서 작업을 수행하려는 경우

는, 어쩌면 당신은 같은 것을 할 수 있습니다

import functools 
view = functools.partials(view, cache_size=0) 

이 방법을, 당신은이에 if 문을 추가 디버그 모드에있는 경우에만 할 수 있습니다 코드 if bottle.DEBUG.

+0

cache_size = 0 인수가 view() 데코레이터 또는 template() 함수를 사용하여 나에게 적합하지 않기 때문에 성능이 저하되었습니다. 또한 (reloader = True)를 실행하면 "로컬 변수 'lockfile'이 할당 전에 참조됩니다." – arkanciscan

+0

@arkanciscan이 버그는 아마도 내 responseq와 관련이 없지만 괜찮습니다. 아시다시피, 나는 귀하의 의견을 병 (https://github.com/defnull/bottle/issues/278)에 문제로보고했습니다. github의 버그에 대한 자세한 정보를 제공 할 수 있습니까? 어떤 서버 어댑터를 사용하고 있습니까? 감사! – iurisilvio

+0

+1 버그 보고서, 감사합니다 :) – defnull

5

내부적으로 병 캐쉬 템플릿 (Jinja2 캐싱과 독립적 임). bottle.debug(True) 또는 bottle.run(..., debug=True)을 통해 캐시를 사용 중지하거나 bottle.TEMPLATES.clear()을 사용하여 캐시를 지울 수 있습니다.

+0

응답 해 주셔서 감사합니다. 나는 병에 대해 몰랐다. 실험실. 명확한(), 편리하게 올 수 있었다! 프로젝트 처음부터 bottle.debug (True)를 설정 했으므로 Jinja의 캐시를 구성하는 데 문제가 있었다고 확신합니다. – leted

+0

bottle.run을 실행하기 전에 bottle.debug (True)가 실행 중입니다. bottle.run의 디버그 인수는 기본값이 False로 지정되어 있지 않으면 bottle.DEBUG를 덮어 씁니다. –