Django TemplateDoesNotExist

Django REST Framework 中未配置 INSTALLED_APPS 导致 api.html 模板不存在

一、问题背景

在学习 Django REST Framework(DRF)的过程中,新建了一个 home 应用,并使用 DRF 的 APIView 编写一个简单的测试接口。

home/views.py 代码如下:

复制代码
from django.shortcuts import render

# Create your views here.

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status


class HomeAPIView(APIView):
    def get(self, request):
        print("hello")
        brother = ['jinx', 'jin', 'jinxin']
        return Response(brother, status.HTTP_200_OK)

对应的 home/urls.py

复制代码
from django.urls import path
from . import views

urlpatterns = [
    path("test", views.HomeAPIView.as_view()),
]

项目主路由:

复制代码
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('home/', include("home.urls")),
]

启动 Django 开发服务器后访问:

复制代码
http://127.0.0.1:8000/home/test

此时接口并没有正常返回数据,而是出现了 500 Internal Server Error


二、报错信息

Django 控制台中的关键错误为:

复制代码
ERROR Internal Server Error: /home/test

Traceback (most recent call last):
    ...
django.template.exceptions.TemplateDoesNotExist:
    rest_framework/api.html

其中最关键的一行是:

复制代码
TemplateDoesNotExist: rest_framework/api.html

看到这个错误时,最开始容易怀疑是 View 代码的问题。

但实际上,当前 View 中只有非常简单的代码:

复制代码
def get(self, request):
    print("hello")
    brother = ['jinx', 'jin', 'jinxin']
    return Response(brother, status.HTTP_200_OK)

这里没有数据库操作,也没有 Redis 操作,甚至没有复杂的业务逻辑。

因此问题并不在 View 内部的数据处理。

页面访问:


三、首先确认 View 是否执行

为了确认问题发生在哪里,在 View 中加入:

复制代码
print("hello")

访问:

复制代码
/home/test

如果 Django 控制台能够正常打印:

复制代码
hello

但是浏览器仍然返回:

复制代码
500 Internal Server Error

就说明:

HomeAPIView 已经成功执行,问题发生在 View 返回 Response 之后。

这也是排查 Django REST Framework 问题时一个非常有用的思路。

整个请求过程可以理解为:

复制代码
浏览器
   ↓
/home/test
   ↓
URL 路由匹配
   ↓
HomeAPIView
   ↓
get()
   ↓
print("hello")
   ↓
生成数据
   ↓
Response()
   ↓
DRF Renderer
   ↓
加载 rest_framework/api.html
   ↓
模板不存在
   ↓
500 Internal Server Error

所以,看到 TemplateDoesNotExist 后,不应该继续修改 get() 中的业务代码,而应该检查 DRF 的配置。


四、问题原因

检查项目的 settings.py 后发现,虽然代码已经可以正常导入:

复制代码
from rest_framework.views import APIView
from rest_framework.response import Response

但是 INSTALLED_APPS 中没有配置:

复制代码
'rest_framework',

也就是说:

DRF 的 Python 包虽然已经安装,但是没有正确注册到 Django 项目中。

这是 Django 初学者比较容易遇到的问题。

需要注意:

Python 中能够 import rest_framework,并不代表 DRF 已经完成 Django 项目的配置。

Python 包安装和 Django App 注册是两个不同的概念。


五、解决方法

打开项目的 settings.py,找到:

复制代码
INSTALLED_APPS = [
    ...
]

添加:

复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'rest_framework',

    'home',
]

其中最关键的是:

复制代码
'rest_framework',

保存之后重新启动 Django:

复制代码
python manage.py runserver 0.0.0.0:8000

再次访问:

复制代码
http://127.0.0.1:8000/home/test

此时即可正常使用 DRF 的接口。


六、为什么会出现 rest_framework/api.html

看到:

复制代码
TemplateDoesNotExist: rest_framework/api.html

可能会产生一个疑问:

我明明是在写 API,为什么 Django 会去找 HTML 模板?

这是因为 DRF 不仅可以返回 JSON 数据,还提供了一个非常方便的 Browsable API(可浏览 API)

当前 View 返回的是:

复制代码
return Response(brother, status.HTTP_200_OK)

这里使用的是 DRF 的:

复制代码
Response

而不是 Django 原生的:

复制代码
HttpResponse

DRF 会根据客户端请求选择合适的 Renderer。

当直接使用浏览器访问接口时,DRF 可以使用 Browsable API 以网页形式展示接口。

因此请求会进入 DRF 的渲染过程,并尝试加载:

复制代码
rest_framework/api.html

如果 Django 没有正确注册 rest_framework,就可能无法找到这个模板,从而出现:

复制代码
TemplateDoesNotExist:
rest_framework/api.html

因此,这个错误并不意味着需要自己创建一个:

复制代码
api.html

真正应该检查的是 DRF 是否正确配置。


七、为什么 API 本身实际上没有问题?

本次代码非常简单:

复制代码
class HomeAPIView(APIView):
    def get(self, request):
        print("hello")
        brother = ['jinx', 'jin', 'jinxin']
        return Response(brother, status.HTTP_200_OK)

其中:

复制代码
brother = ['jinx', 'jin', 'jinxin']

只是创建一个普通 Python 列表。

然后:

复制代码
return Response(brother, status.HTTP_200_OK)

将数据交给 DRF 处理。

如果最终出现:

复制代码
TemplateDoesNotExist: rest_framework/api.html

说明:

复制代码
View
 ↓
已经执行
 ↓
Response
 ↓
DRF 响应渲染
 ↓
出现异常

因此可以确定,这不是 brother 列表的问题,也不是 get() 方法本身的问题。


八、不要把"安装"和"注册"混为一谈

这个问题最值得记录的地方,就是 Django 第三方应用的配置方式。

例如安装 DRF:

复制代码
pip install djangorestframework

解决的是:

Python 环境中有没有 DRF 这个包。

而:

复制代码
INSTALLED_APPS = [
    ...
    'rest_framework',
]

解决的是:

Django 项目有没有正确加载这个应用。

两者并不是完全相同的概念。

因此,在使用 Django 第三方应用时,不能只确认:

复制代码
import rest_framework

能够正常执行。

还需要根据第三方应用的要求完成 Django 项目配置。


九、排查这类问题的方法

以后如果在 Django REST Framework 中遇到类似问题,可以按照下面的思路排查。

1. 先判断路由有没有匹配

如果返回:

复制代码
404 Not Found

优先检查:

复制代码
urls.py

例如:

复制代码
path('home/', include("home.urls"))

以及:

复制代码
path("test", views.HomeAPIView.as_view())

是否正确。


2. 如果是 500,查看 Traceback

不要只看:

复制代码
500 Internal Server Error

而应该找到 Traceback 最后面的异常。

本次真正有价值的信息是:

复制代码
TemplateDoesNotExist:
rest_framework/api.html

3. 判断 View 有没有执行

可以临时添加:

复制代码
print("hello")

如果控制台出现:

复制代码
hello

说明 View 已经执行。

这时候就应该继续检查:

复制代码
Response
Renderer
Template
DRF 配置

而不是继续修改 View 的业务逻辑。


4. 检查 INSTALLED_APPS

使用 DRF 时确认:

复制代码
INSTALLED_APPS = [
    ...
    'rest_framework',
]

是否存在。


十、总结

这次问题表面上看是:

复制代码
访问 /home/test
        ↓
500

真正的错误却不是 View:

复制代码
TemplateDoesNotExist:
rest_framework/api.html

最终定位发现,是因为项目虽然使用了 Django REST Framework,但是没有在 INSTALLED_APPS 中注册:

复制代码
'rest_framework',

导致 DRF 在处理 Response 时无法正确加载自己的模板资源。

整个问题可以概括为:

复制代码
安装 DRF
   ↓
可以 import rest_framework
   ↓
但没有加入 INSTALLED_APPS
   ↓
APIView 正常执行
   ↓
Response 正常创建
   ↓
DRF 尝试渲染 Browsable API
   ↓
找不到 rest_framework/api.html
   ↓
TemplateDoesNotExist
   ↓
500

最终解决方案:

复制代码
INSTALLED_APPS = [
    ...
    'rest_framework',
]

这次问题也说明,在 Django 项目中使用第三方应用时,需要同时关注 Python 包安装Django 项目配置。仅仅能够导入第三方包,并不意味着它已经完成了 Django 所需要的全部配置。

相关推荐
方便面不加香菜1 小时前
MySQL 复合查询
数据库·mysql
花花鱼1 小时前
MySQL Illegal mix of collations 全解|字符集与排序规则冲突原理、分层排错、通用解决方案(适配5.7/8.0迁移)
数据库·mysql
Wang's Blog1 小时前
PostgreSQL笔记37:数据库性能瓶颈排查方法论与工具链
数据库·笔记·postgresql
oradh11 小时前
Oracle闪回技术操作总结
数据库·oracle·oracle闪回技术操作总结·oracle闪回·flashback技术
ltl12 小时前
RocksDB 并发 Compaction 与 Rate Limiter
数据库
闻道且行之13 小时前
图片处理助手|泊松融合原理 + C++ 工程实现,seamlessClone 三模式一次讲透
数据库·c++·人工智能·opencv
夏炳辉.14 小时前
PostgreSQL 高可用集群核心配置参数全解:从原生流复制到 Patroni 企业级方案
数据库·postgresql
努力的小雨15 小时前
KES 开启 SSL 前,证书、端口和客户端要一起验
数据库
DevOps老兵15 小时前
AI全栈知识07:向量数据库 - Milvus/Chroma实战
数据库·ai·milvus