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
, безуспешно.
Редактировать в соответствии с просьбой Ashok:
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())
3 ответа
Причина этого заключается в том, что загрузчик 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', чтобы добавить к имени шаблона. Это также предполагает, что пользователь никогда не переименует ваше приложение без переименования папки в каталоге шаблонов, что может быть небезопасным предположением, и в этом случае просто жестко закодируйте имя папки в каталоге шаблонов.
Я знаю, что это старая ветка, но я сделал что-то повторно используемое, что позволяет упростить пространство имен. Вы можете загрузить следующее в качестве загрузчика шаблонов. Найдет 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))
App_loader ищет шаблоны в ваших приложениях в порядке, указанном в вашем INSTALLED_APPS. ( http://docs.djangoproject.com/en/dev/ref/templates/api/).
Мое предложение состоит в том, чтобы предварять имя вашего файла шаблона именем приложения, чтобы избежать этих конфликтов имен.
Например, шаблон dir для app1 будет выглядеть так:
templates/
app1_index.html
app1_delete.html
app1_add.html
app1_create.html