Django视图 - 首先从调用app的目录加载模板

jma*_*son 31 django templates

我尝试在我的HTML模板上保持一个有点一致的命名方案.即index.html for main,delete.html for delete page等等.但是app_directories加载器总是似乎从按字母顺序排列的应用程序加载模板.

有没有办法总是先在调用应用程序的templates目录中检查匹配?

我的相关设置settings.py:

PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))

TEMPLATE_LOADERS = (
    'django.template.loaders.app_directories.load_template_source',
    'django.template.loaders.filesystem.load_template_source',
)
TEMPLATE_DIRS = (
    os.path.join(PROJECT_PATH, 'templates'),
)
Run Code Online (Sandbox Code Playgroud)

我试过改变顺序TEMPLATE_LOADERS,没有成功.


按照Ashok的要求编辑:

每个应用程序的目录结构:

templates/
    index.html
    add.html
    delete.html
    create.html
models.py
test.py
admin.py
views.py
Run Code Online (Sandbox Code Playgroud)

在每个应用程序的views.py中:

def index(request):
    # code...
    return render_to_response('index.html', locals())

def add(request):
    # code...
    return render_to_response('add.html', locals())

def delete(request):
    # code...
    return render_to_response('delete.html', locals())

def update(request):
    # code...
    return render_to_response('update.html', locals())
Run Code Online (Sandbox Code Playgroud)

Dan*_*iel 49

这样做的原因是app_directories加载器与将每个应用程序的模板文件夹添加到TEMPLATE_DIRS设置基本相同,例如像

TEMPLATE_DIRS = (
    os.path.join(PROJECT_PATH, 'app1', 'templates'),
    os.path.join(PROJECT_PATH, 'app2', 'template'),
    ...
    os.path.join(PROJECT_PATH, 'templates'),
)
Run Code Online (Sandbox Code Playgroud)

问题在于,正如您所提到的,index.html将始终位于app1/templates/index.html中,而不是任何其他应用.没有简单的解决方案可以在不修改app_directories加载器和使用内省或传递应用程序信息的情况下神奇地修复此行为,这有点复杂.更简单的解决方案

  • 保持您的settings.py原样
  • 使用应用程序的名称在每个应用程序的模板文件夹中添加一个子目录
  • 在"app1/index.html"或"app2/index.html"等视图中使用模板

有关更具体的示例:

project
    app1
        templates
            app1
                index.html
                add.html
                ...
        models.py
        views.py
        ...
    app2
        ...
Run Code Online (Sandbox Code Playgroud)

然后在视图中:

def index(request):
    return render_to_response('app1/index.html', locals())
Run Code Online (Sandbox Code Playgroud)

您甚至可以编写一个包装器来自动将应用程序名称添加到您的所有视图中,甚至可以将其扩展为使用内省,例如:

def render(template, data=None):
    return render_to_response(__name__.split(".")[-2] + '/' + template, data)

def index(request):
    return render('index.html', locals())
Run Code Online (Sandbox Code Playgroud)

_____名称_____.split(".")[ - 2]假定文件位于包中,因此它会将"app1.views"转换为"app1"以添加到模板名称之前.这也假设用户永远不会重命名您的应用程序而不重命名模板目录中的文件夹,这可能不是一个安全的假设,在这种情况下只需硬编码模板目录中的文件夹名称.

  • 这几乎是我唯一想念的CakePHP :)我希望他们有一天能添加它. (2认同)

hid*_*jan 7

我知道这是一个旧线程,但我做了一些可重用的东西,允许更简单的命名空间.您可以将以下内容加载为模板加载器.它会找到appname/index.htmlappname/templates/index.html.

Gist可在此处获取:https://gist.github.com/871567

"""
Wrapper for loading templates from "templates" directories in INSTALLED_APPS
packages, prefixed by the appname for namespacing.

This loader finds `appname/templates/index.html` when looking for something
of the form `appname/index.html`.
"""

from django.template import TemplateDoesNotExist
from django.template.loaders.app_directories import app_template_dirs, Loader as BaseAppLoader

class Loader(BaseAppLoader):
    '''
    Modified AppDirecotry Template Loader that allows namespacing templates
    with the name of their app, without requiring an extra subdirectory
    in the form of `appname/templates/appname`.
    '''
    def load_template_source(self, template_name, template_dirs=None):
        try:
            app_name, template_path = template_name.split('/', 1)
        except ValueError:
            raise TemplateDoesNotExist(template_name)

        if not template_dirs:
            template_dirs = (d for d in app_template_dirs if
                    d.endswith('/%s/templates' % app_name))

        return iter(super(Loader, self).load_template_source(template_path,
                template_dirs))
Run Code Online (Sandbox Code Playgroud)


Chr*_*lor 5

app_loader在您的应用程序中查找模板,以便在INSTALLED_APPS中指定模板。(http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types)。

我的建议是在模板文件的名称前加上应用程序名称,以避免这些命名冲突。

例如,app1的模板目录如下所示:

templates/
    app1_index.html
    app1_delete.html
    app1_add.html
    app1_create.html
Run Code Online (Sandbox Code Playgroud)