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 所需要的全部配置。