Django view - загрузка шаблона с момента запуска приложения-приложения
Я пытаюсь сохранить несколько согласованную схему именования в своих 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
В каждом приложении 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())
Ответы
Ответ 1
Причиной этого является то, что загрузчик 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())
_____ name _____. split ( "." ) [- 2] предполагает, что файл находится внутри пакета, поэтому он будет поворачиваться, например. 'app1.views' в 'app1' для добавления к имени шаблона. Это также предполагает, что пользователь никогда не переименует ваше приложение, не переименовав папку в каталоге шаблонов, что может быть не безопасным, и в этом случае просто скопируйте имя папки в каталоге шаблонов.
Ответ 2
Я знаю, что это старый поток, но я сделал что-то многоразовое, что позволяет упростить пространство имен. Вы можете загрузить следующее как загрузчик шаблонов. Он найдет appname/index.html
в appname/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))
Ответ 3
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