代码之家  ›  专栏  ›  技术社区  ›  jmagnusson

Django View-首先从调用应用程序的dir加载模板

  •  31
  • jmagnusson  · 技术社区  · 16 年前

    我尝试在HTML模板上保持某种一致的命名方案。也就是说,index.html用于main,delete.html用于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'),
    )
    

    我试过改变 TEMPLATE_LOADERS 没有成功。


    按ashok要求编辑:

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

    templates/
        index.html
        add.html
        delete.html
        create.html
    models.py
    test.py
    admin.py
    views.py
    

    在每个应用程序的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())
    
    3 回复  |  直到 11 年前
        1
  •  49
  •   Daniel    16 年前

    这是因为应用程序目录加载程序本质上与将每个应用程序的模板文件夹添加到模板目录设置相同,例如

    TEMPLATE_DIRS = (
        os.path.join(PROJECT_PATH, 'app1', 'templates'),
        os.path.join(PROJECT_PATH, 'app2', 'template'),
        ...
        os.path.join(PROJECT_PATH, 'templates'),
    )
    

    问题在于,正如您所提到的,index.html将始终位于app1/templates/index.html中,而不是任何其他应用程序中。如果不修改app_目录加载器并使用内省或传递app信息,就无法轻松地解决此问题,这会变得有点复杂。更简单的解决方案:

    • 保持设置.py不变
    • 在每个应用的templates文件夹中添加一个子目录,其中包含应用的名称
    • 在“app1/index.html”或“app2/index.html”等视图中使用模板

    更具体的例子是:

    project
        app1
            templates
                app1
                    index.html
                    add.html
                    ...
            models.py
            views.py
            ...
        app2
            ...
    

    然后在视图中:

    def index(request):
        return render_to_response('app1/index.html', locals())
    

    您甚至可以编写一个包装器来自动为所有视图预先准备应用程序名,甚至可以扩展到使用自省,例如:

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

    _uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu.split(“.”)[-2]假定文件在包中,因此它会将“app1.views”转换为“app1”,以预先设置模板名称。这还假定用户在不重命名模板目录中的文件夹的情况下永远不会重命名您的应用程序,这可能不是一个安全的假设,在这种情况下,只需硬编码模板目录中文件夹的名称。

        2
  •  7
  •   hidde-jan    15 年前

    我知道这是一个旧线程,但我做了一些可重用的东西,允许更简单的名称间距。您可以将以下内容作为模板加载程序加载。它会发现 appname/index.html 在里面 appname/templates/index.html .

    这里提供的要点: 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))
    
        3
  •  4
  •   Chris Lawlor    16 年前

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

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

    例如,app1的模板dir如下所示:

    templates/
        app1_index.html
        app1_delete.html
        app1_add.html
        app1_create.html