Django view - сначала загрузите шаблон из директории вызывающего приложения - PullRequest
31 голосов
/ 22 июня 2010

Я стараюсь придерживаться несколько согласованной схемы именования в моих HTML-шаблонах.Т.е. index.html для main, delete.html для страницы удаления и пр.Но загрузчик 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, но безуспешно.

Редактировать в соответствии с просьбой Ашока:

Структура Dir каждого приложения:

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

В представлениях каждого приложения.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 ]

49 голосов
/ 22 июня 2010

Причина этого заключается в том, что загрузчик 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'),
)

Проблема в том, что, как вы упомянули, 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
        ...

Тогда во взглядах:

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())

_____ имя _____. Split (".") [- 2] предполагает, что файл находится в пакете, поэтому он превратится, например, в. 'app1.views' в 'app1', чтобы добавить к имени шаблона. Это также предполагает, что пользователь никогда не переименует ваше приложение без переименования папки в каталоге шаблонов, что не может быть безопасным предположением, и в этом случае просто жестко закодируйте имя папки в каталоге шаблонов.

7 голосов
/ 16 марта 2011

Я знаю, что это старая ветка, но я сделал что-то повторно используемое, что позволяет упростить пространство имен.Вы можете загрузить следующее в качестве загрузчика шаблонов.Он найдет 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))
4 голосов
/ 22 июня 2010

app_loader ищет шаблоны в ваших приложениях в порядке, указанном в вашем INSTALLED_APPS.(http://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types).

Мое предложение состоит в том, чтобы предвосхитить имя вашего файла шаблона именем приложения, чтобы избежать этих конфликтов имен.

Например, каталог dir для app1 будет выглядеть так:

templates/
    app1_index.html
    app1_delete.html
    app1_add.html
    app1_create.html
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...