Django模板不存在?

244

我的本地机器上运行的是Ubuntu 8.10,Python 2.5 和 Nginx,Django构建自最新的开发主干分支。

对于我请求的每个URL,它都会抛出以下错误:

  

TemplateDoesNotExist at /appname/path appname/template_name.html

     

Django尝试按此顺序加载这些模板:   *使用加载器django.template.loaders.filesystem.function:   *使用加载器django.template.loaders.app_directories.function:

     

TEMPLATE_DIRS     ('/usr/lib/python2.5/site-packages/projectname/templates')

在这种情况下,它是否在寻找/usr/lib/python2.5/site-packages/projectname/templates/appname/template_name.html?奇怪的是,该文件实际上存在于磁盘上。为什么Django无法定位它?

我在远程服务器上使用Python 2.6和Ubuntu 9.04运行相同的应用程序而没有这样的问题。其他设置也是一样的。

我的本地机器是否存在任何配置错误,或者我应该查看可能导致此类错误的问题?

在我的settings.py中,我已经指定了:

SETTINGS_PATH = os.path.normpath(os.path.dirname(__file__))
# Find templates in the same folder as settings.py.
TEMPLATE_DIRS = (
    os.path.join(SETTINGS_PATH, 'templates'),
)

应该查找以下文件:

  • /usr/lib/python2.5/site-packages/projectname/templates/appname1/template1.html
  • /usr/lib/python2.5/site-packages/projectname/templates/appname1/template2.html
  • /usr/lib/python2.5/site-packages/projectname/templates/appname2/template3.html
  • ...

以上所有的文件都存在于磁盘上。

已解决

我尝试了以下方法后,现在它可以工作:

chown -R www-data:www-data /usr/lib/python2.5/site-packages/projectname/*

这很奇怪,我在远程服务器上不需要这样做就可以使它工作。


您的TEMPLATE_DIRS是否可被Web服务器读取? - Jordan Messina
@Jordan,TEMPLATE_DIRS对root用户可访问就足够了。这是在远程服务器上配置的,目前正常工作。 - jack
32个回答

267

第一种解决方案:

这些设置

TEMPLATE_DIRS = (
    os.path.join(SETTINGS_PATH, 'templates'),
)

这意味着Django将查找您项目下templates/目录中的模板。

假设您的Django项目位于/usr/lib/python2.5/site-packages/projectname/,则在设置中,django将在/usr/lib/python2.5/site-packages/projectname/templates/下查找模板。

因此,在这种情况下,我们需要将我们的模板结构移动到如下所示:

/usr/lib/python2.5/site-packages/projectname/templates/template1.html
/usr/lib/python2.5/site-packages/projectname/templates/template2.html
/usr/lib/python2.5/site-packages/projectname/templates/template3.html

第二种解决方案:

如果仍然不起作用,并且假设您已经在settings.py中按如下配置了应用程序:

INSTALLED_APPS = (
    'appname1',
    'appname2',
    'appname3',
)

默认情况下,Django会加载每个已安装应用程序下的templates/目录中的模板。因此,针对您的目录结构,我们希望将模板移动到以下位置:

/usr/lib/python2.5/site-packages/projectname/appname1/templates/template1.html
/usr/lib/python2.5/site-packages/projectname/appname2/templates/template2.html
/usr/lib/python2.5/site-packages/projectname/appname3/templates/template3.html

SETTINGS_PATH 可能默认情况下未被定义。在这种情况下,您需要在 settings.py 中定义它:

import os
SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__))

5
@jpartogi,我尝试了两种方法,但都没有起作用。我甚至试图在render_to_response()参数中使用绝对路径来引用模板,但仍然无法工作。 - jack
1
将不同应用程序的每个模板放在一个名为“templates”的目录中并不是一个好的设计。但是,据我所知,在将您的“APP_NAME”添加到“settings.py”之后,“django”可能会在位于“APP_DIR”下的目录中搜索应用程序的模板。因此,您可以将各种应用程序的模板分开。(Django 1.7 - .1.9) - Alston
1
将项目名称添加到“INSTALLED_APP”列表中解决了它。谢谢。 - user2284357
这不是 /usr/lib/python2.5/site-packages/projectname/appname2/templates/appname2/template2.html。 - Josh
2
Django TEMPLATE_DIRS自1.8版本开始已被弃用,https://docs.djangoproject.com/en/1.8/ref/settings/#template-dirs。 - Emily
显示剩余5条评论

92

找到这个元组:

    import os
    SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__))

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

你需要将该字符串添加到“DIRS”中

os.path.join(BASE_DIR, 'templates')

所以您总共需要:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(SETTINGS_PATH, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

31
SETTINGS_PATH 没有被定义在任何地方,所以我不认为这个答案会起作用。也许你的意思是 BASE_DIR - sofly
2
定义 SETTINGS_PATH = os.path.dirname(os.path.dirname(file)) - Shapon Pal
1
我认为Shapon Pal的意思是SETTINGS_PATH = os.path.dirname(os.path.dirname(__file__)),而不是file - mic
谢谢,这对我有用。在设置Django时需要协调很多小细节,所以这可能适用于某些人但不适用于其他人。此帖子中还有许多其他回复中的好解决方案! - Mohammad Athar

80

如果您从头开始添加一个 app 时遇到了这个问题,那可能是因为您遗漏了一些 settings。在添加一个 app 时需要进行三个步骤。

1、创建目录和模板文件。

假设您有一个名为 mysite 的项目,您想要添加一个名为 your_app_nameapp。请按以下方式将模板文件放置在 mysite/your_app_name/templates/your_app_name 中。

├── mysite
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── your_app_name
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── templates
│   │   └── your_app_name
│   │       └── my_index.html
│   ├── urls.py
│   └── views.py

2、将app添加到INSTALLED_APPS中。

修改settings.py

INSTALLED_APPS = [
    ...
    'your_app_name',
    ...
]

3、将你的app目录添加到TEMPLATES中的DIRS

修改settings.py

添加os导入。

import os
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates'),
                 os.path.join(BASE_DIR, 'your_app_name', 'templates', 'your_app_name'),
                ...
                ]
    }
]

1
这是我在使用Django 2.2.7时找到的唯一可行的解决方案。 - Jhonatas Kleinkauff
4
就我而言,只有第二个步骤缺失。我可以将DIRS数组保留为空,它仍然有效,并在应用程序的正确模板目录中查找模板。 - Shri Shinde
9
我的应用程序刚刚缺少了INSTALLED_APPS。谢谢! - Rami Alloush
这种方法对我有效。感谢出色的分享。 - Shirley
讲解得非常清楚,谢谢!这解决了我的问题。 - Steve

15

在设置 .py 中,移除 TEMPLATE_LOADERS 和 TEMPLATE_DIRS,然后添加

TEMPLATES = [
 {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': ['/home/jay/apijay/templates',],
    'APP_DIRS': True,
    'OPTIONS': {
        'context_processors': [
            'django.template.context_processors.debug',
            'django.template.context_processors.request',
            'django.contrib.auth.context_processors.auth',
            'django.contrib.messages.context_processors.messages',
        ],
    },
 },
]

11

我有一个很尴尬的问题...

我之所以会遇到这个错误,是因为我匆忙操作,忘记将应用程序添加到 INSTALLED_APPS 中。你可能认为 Django 应该抛出更具描述性的错误。


8
在测试版本为3的Django中,您需要将新应用程序添加到已安装的应用程序中。对于一个 Django 应用程序,不需要进行其他代码更改。
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'addyourappnamehere'
]

7
2023年5月更新: templates文件夹可以放在django-project文件夹下,或者放在每个app文件夹下,如下所示:
django-project
 |-core
 │  |-settings.py
 │  └-urls.py
 |-app1
 |  |-urls.py
 |  └-views.py
 |-app2
 |  |-urls.py
 |  └-views.py
 └-templates # Here
    |-app1
    |  └-a1.html
    └-app2
       └-a2.html

或者:

django-project
 |-core
 │  |-settings.py
 │  └-urls.py
 |-app1
 |  |-urls.py
 |  |-views.py
 |  └-templates # Here
 |     └-app1
 |        └-a1.html
 └-app2
    |-urls.py
    |-views.py
    └-templates # Here
       └-app2
          └-a2.html

例如,首先您需要在settings.py中将"app1""app2"设置为INSTALLED_APPS,如下所示:
# "core/settings.py"

INSTALLED_APPS = [
    ...
    "app1",
    "app2",
]

那么如果 templates 文件夹就在 django-project 文件夹下面,如下所示:

django-project
 |-core
 │  |-settings.py
 │  └-urls.py
 |-app1
 |  |-urls.py
 |  └-views.py
 |-app2
 |  |-urls.py
 |  └-views.py
 └-templates # Here
    |-app1
    |  └-a1.html
    └-app2
       └-a2.html

然后,您需要将 BASE_DIR / 'templates' 设置为"DIRS"中的TEMPLATESsettings.py中如下所示。*我建议将 templates 文件夹放在 django-project 文件夹的下面,如上所示,因为您可以轻松管理模板:

# "core/settings.py"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            BASE_DIR / 'templates' # Here
        ],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

如果templates文件夹就在每个app文件夹下面,如下所示:

django-project
 |-core
 │  |-settings.py
 │  └-urls.py
 |-app1
 |  |-urls.py
 |  |-views.py
 |  └-templates # Here
 |     └-app1
 |        └-a1.html
 └-app2
    |-urls.py
    |-views.py
    └-templates # Here
       └-app2
          └-a2.html

然后,您需要保持"DIRS"为空(这是默认值),而不将BASE_DIR/'templates'设置为"DIRS",如下所示,在settings.py中的TEMPLATES中:

# "core/settings.py"

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [], # Keep it empty
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

然后,在app1/views.pyapp2/views.py中定义test()如下所示。请注意,您需要在render()中设置"app1/a1.html""app2/a2.html"而不是仅仅设置"a1.html""a2.html",如下所示:

# "app1/views.py"

from django.shortcuts import render

def test(request):         # Don't set just "a1.html"
    return render(request, "app1/a1.html")

# "app2/views.py"

from django.shortcuts import render

def test(request):         # Don't set just "a2.html"
    return render(request, "app2/a2.html")

然后,在app1/urls.pyapp2/urls.py中,将每个app1app2test视图设置如下所示:
# "app1/urls.py"

from django.urls import include, path

from . import views

app_name = "app1"

urlpatterns = [
    path("", views.test, name='test'), # Here
]

# "app2/urls.py"

from django.urls import include, path

from . import views

app_name = "app2"

urlpatterns = [
    path("", views.test, name='test'), # Here
]

然后,在core/urls.py中设置app1app2的每个urls.py,如下所示,然后app1app2的模板将被渲染而不会出现任何错误:

# "core/urls.py"

from django.urls import include, path

urlpatterns = [
    ...
    path("app1/", include('app1.urls')), # Here
    path("app2/", include('app2.urls'))  # Here
]

最后,我再次建议将templates文件夹放在django-project文件夹下面,如下所示,因为您可以轻松地在一个地方管理模板:
django-project
 |-core
 │  |-settings.py
 │  └-urls.py
 |-app1
 |  |-urls.py
 |  └-views.py
 |-app2
 |  |-urls.py
 |  └-views.py
 └-templates # Here
    |-app1
    |  └-a1.html
    └-app2
       └-a2.html

6
对于Django版本1.9,我添加了以下内容:
'DIRS': [os.path.join(BASE_DIR, 'templates')], 

将代码行添加到settings.py的Templates块中

它可以很好地运作


5
Django的“TemplateDoesNotExist”错误简单地意味着框架找不到模板文件。
要使用模板加载API,您需要告诉框架您存储模板的位置。这个位置在您的设置文件(“settings.py”)中通过“TEMPLATE_DIRS”设置来实现。默认情况下,它是一个空元组,因此此设置告诉Django的模板加载机制要查找模板的位置。
选择一个目录以存储您的模板,并将其添加到TEMPLATE_DIRS中,例如:
TEMPLATE_DIRS = (
  '/home/django/myproject/templates',
)

4
只是一种猜测,但请查看Django模板加载的这篇文章。特别是,请确保在您的TEMPLATE_LOADERS列表中拥有django.template.loaders.app_directories.Loader

这对我有效。从文件系统上的Django应用程序加载模板。对于INSTALLED_APPS中的每个应用,加载器都会查找templates子目录。如果该目录存在,则Django会在其中查找模板。<br> TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'APP_DIRS': True, }] - Vijay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接