app-engine-patchで作ったのをローカルのDjangoに移植しようとしてTemplateDoesNotExist

  • まずこのエラーになるまえにこれは済んでるはず
-    from ragendja.template import render_to_response
+    from django.shortcuts import render_to_response
  • TemplateDoesNotExist at / ,... と大量のメッセージが表示される
    • ragendja.template.render_to_responseが第一引数はrequestなんだけど、django.shortcuts.render_to_responseの第一引数はテンプレート名だ
  • 「foo/index.htmlはない」と言われる
    • これはrajendra.templateで定義されているapp_prefixed_loaderの機能だ。
# The following defines a template loader that loads templates from a specific
# app based on the prefix of the template path:
# get_template("app/template.html") => app/templates/template.html
# This keeps the code DRY and prevents name clashes.
def app_prefixed_loader(template_name, template_dirs=None):
    packed = template_name.split('/', 1)
    if len(packed) == 2 and packed[0] in app_template_dirs:
        path = os.path.join(app_template_dirs[packed[0]], packed[1])
        try:
            return (open(path).read().decode(settings.FILE_CHARSET), path)
        except IOError:
            pass
    raise TemplateDoesNotExist, template_name
app_prefixed_loader.is_usable = True

で、このローダを使うという情報がどこで登録されているかというとsettings_pre.pyの中なので

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.load_template_source',
    'ragendja.template.app_prefixed_loader',
    'django.template.loaders.app_directories.load_template_source',
)

というわけで最低限必要な以下のものを持ってきてTEMPLATE_LOADERSに設定を書けば動く。「app_template_dirs = get_app_dirs('templates')」とか書いてあるのを見て「やだなこのモジュールをインポートするの」と思って切り出すことにしたのだけど、結局その嫌だった行は必須だということがわかったので切り出して新しいモジュールを作る必要はなかったかもしれない。面倒なので調べない。

import settings
import os

# from common/appenginepatch/ragendja/apputils.py
def import_module(module_name):
    ...

def get_app_modules(module_name=None):
    ...

def get_app_dirs(subdir=None):
    ...

# from common/appenginepatch/ragendja/templates.py
def app_prefixed_loader(template_name, template_dirs=None):
    ...

app_template_dirs = get_app_dirs('templates')

で、とりあえず画面が出るようになった。

  • CSSとかへのリンクが切れている
    • urls.pyでdjango.views.static.serveを使う。