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

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐