DRF 教程:从零开始搭建 RESTful API – wiki大全


DRF 教程:从零开始搭建 RESTful API

欢迎来到 Django REST Framework (DRF) 的世界!在本教程中,我们将一步步地学习如何使用 DRF 从零开始搭建一个功能完善的 RESTful API。无论您是 Django 的初学者还是希望将其与 API 开发结合的资深开发者,本文都将为您提供清晰的指导。

什么是 RESTful API?为什么选择 DRF?

在深入代码之前,让我们快速了解一下基本概念:

  • REST (Representational State Transfer): 是一种软件架构风格,用于设计网络应用程序。它定义了一组约束,当一个系统遵循这些约束时,它就被认为是 RESTful 的。RESTful API 的核心思想是使用标准的 HTTP 方法(GET, POST, PUT, DELETE 等)对资源进行操作。
  • API (Application Programming Interface): 是一种允许不同软件系统之间进行通信的接口。
  • RESTful API: 就是遵循 REST 架构风格的 API,它通常通过 HTTP 协议进行通信,并以 JSON 或 XML 等格式交换数据。

为什么选择 Django REST Framework (DRF)?

Django 本身是一个功能强大的 Web 框架,但它主要面向构建传统的 Web 应用程序,提供 HTML 页面。当我们需要构建现代的、前后端分离的应用程序,或者为移动应用提供数据接口时,就需要一个专门的工具来创建 API。DRF 正是为此而生:

  • Django 的扩展: 它建立在 Django 之上,充分利用了 Django 的 ORM、认证系统和各种插件。如果您熟悉 Django,那么学习 DRF 将会非常顺利。
  • 易于使用: 提供了强大的工具集,使得构建 API 变得非常简单快捷。
  • 功能丰富: 包括序列化器、认证、权限、限流、视图集、路由器等开箱即用的功能。
  • 强大的社区和文档: 拥有活跃的社区和详尽的官方文档,遇到问题很容易找到解决方案。
  • 可浏览的 API: 自动生成美观且易于调试的 Web 可浏览 API,方便开发和测试。

现在,让我们开始动手搭建第一个 API 吧!

1. 环境准备与项目初始化

在开始之前,请确保您的系统已安装 Python 和 pip。

1.1 创建并激活虚拟环境 (推荐)

良好的开发实践是从虚拟环境开始。

“`bash

创建虚拟环境

python -m venv venv

激活虚拟环境 (Windows)

.\venv\Scripts\activate

激活虚拟环境 (macOS/Linux)

source venv/bin/activate
“`

1.2 安装 Django 和 Django REST Framework

激活虚拟环境后,安装必要的库。

bash
pip install Django djangorestframework

1.3 创建 Django 项目和应用

我们将创建一个名为 myapi_project 的项目和 todos 应用,用于管理待办事项。

“`bash

创建 Django 项目

django-admin startproject myapi_project .

创建 Django 应用

python manage.py startapp todos
“`

现在您的项目结构应该类似这样:

myapi_project/
├── manage.py
├── myapi_project/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── todos/
├── migrations/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py

1.4 注册应用和 DRF

打开 myapi_project/settings.py,在 INSTALLED_APPS 列表中添加 rest_framework 和您的应用 todos

“`python

myapi_project/settings.py

INSTALLED_APPS = [
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
# 第三方应用
‘rest_framework’,
# 自己的应用
‘todos’,
]

… 其他设置 …

“`

2. 定义数据模型 (Models)

我们将创建一个简单的 Todo 模型,包含 title(标题)、description(描述)和 completed(是否完成)字段。

打开 todos/models.py 并添加以下代码:

“`python

todos/models.py

from django.db import models

class Todo(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(blank=True, null=True)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return self.title

“`

2.1 数据库迁移

定义模型后,需要进行数据库迁移。

bash
python manage.py makemigrations todos
python manage.py migrate

3. 创建序列化器 (Serializers)

序列化器是 DRF 的核心组件之一。它们负责将 Django 模型实例(复杂数据类型)转换为 JSON/XML 等可传输的数据格式,以及反之(从传入的 JSON/XML 数据验证并转换回 Django 模型实例)。

todos 应用目录下创建一个新文件 todos/serializers.py

“`python

todos/serializers.py

from rest_framework import serializers
from .models import Todo

class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = (‘id’, ‘title’, ‘description’, ‘completed’, ‘created_at’)
read_only_fields = (‘created_at’,) # created_at 字段只读
“`

这里我们使用了 ModelSerializer,它是一个非常方便的快捷方式,可以自动为模型生成一系列字段。fields 元组指定了我们希望在 API 中公开的模型字段。read_only_fields 用于指定那些只在读取时显示,创建/更新时无需提供的字段。

4. 创建视图 (Views)

视图负责处理传入的 HTTP 请求,与模型交互,并使用序列化器准备响应数据。DRF 提供了多种视图类型,从低级的 APIView 到高级的 ModelViewSet,让您可以根据需求选择合适的抽象级别。

我们将从 APIView 开始,逐步过渡到更简洁的 GenericAPIViewModelViewSet

打开 todos/views.py

4.1 使用 APIView (基础但灵活)

APIView 提供了与 Django View 类似的灵活性,但增加了 DRF 的请求和响应对象、认证、权限和限流等功能。

“`python

todos/views.py (APIView 示例)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404

from .models import Todo
from .serializers import TodoSerializer

class TodoListCreateAPIView(APIView):
“””
列出所有 Todo 或创建一个新的 Todo。
“””
def get(self, request, format=None):
todos = Todo.objects.all()
serializer = TodoSerializer(todos, many=True) # many=True 表示序列化一个查询集
return Response(serializer.data)

def post(self, request, format=None):
    serializer = TodoSerializer(data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class TodoDetailAPIView(APIView):
“””
检索、更新或删除一个 Todo 实例。
“””
def get_object(self, pk):
try:
return Todo.objects.get(pk=pk)
except Todo.DoesNotExist:
raise Http404

def get(self, request, pk, format=None):
    todo = self.get_object(pk)
    serializer = TodoSerializer(todo)
    return Response(serializer.data)

def put(self, request, pk, format=None):
    todo = self.get_object(pk)
    serializer = TodoSerializer(todo, data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

def delete(self, request, pk, format=None):
    todo = self.get_object(pk)
    todo.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

“`

这种方法虽然清晰,但对于简单的 CRUD 操作来说代码量较大,且重复性高。

4.2 使用 GenericAPIView 和 Mixins (更简洁)

DRF 提供了 GenericAPIView,它继承自 APIView,并预设了一些常用的属性和方法,如 querysetserializer_class。结合 mixins(混合类),我们可以更优雅地实现 CRUD 操作。

“`python

todos/views.py (GenericAPIView 和 Mixins 示例)

请注释掉或删除前面的 APIView 示例代码,以免冲突

from rest_framework import generics, mixins

… (models 和 serializers 导入保持不变)

class TodoListCreateGenericView(generics.GenericAPIView,
mixins.ListModelMixin,
mixins.CreateModelMixin):
queryset = Todo.objects.all()
serializer_class = TodoSerializer

def get(self, request, *args, **kwargs):
    return self.list(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
    return self.create(request, *args, **kwargs)

class TodoRetrieveUpdateDestroyGenericView(generics.GenericAPIView,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin):
queryset = Todo.objects.all()
serializer_class = TodoSerializer

def get(self, request, *args, **kwargs):
    return self.retrieve(request, *args, **kwargs)

def put(self, request, *args, **kwargs):
    return self.update(request, *args, **kwargs)

def patch(self, request, *args, **kwargs): # PATCH 用于部分更新
    return self.partial_update(request, *args, **kwargs)

def delete(self, request, *args, **kwargs):
    return self.destroy(request, *args, **kwargs)

“`

这里我们使用了 ListModelMixinCreateModelMixinRetrieveModelMixinUpdateModelMixinDestroyModelMixin,它们提供了实现相应操作的逻辑。

4.3 使用 generics.*APIView (最常用快捷方式)

DRF 进一步封装了 GenericAPIViewmixins 的组合,提供了 generics 模块中的具体视图类。这是最常见且推荐的方式,因为它代码量最少。

“`python

todos/views.py (generics.*APIView 示例)

请注释掉或删除前面的所有视图示例代码,只保留此部分

from rest_framework import generics
from .models import Todo
from .serializers import TodoSerializer

class TodoListCreateAPIView(generics.ListCreateAPIView):
“””
列出所有 Todo 或创建一个新的 Todo。
“””
queryset = Todo.objects.all()
serializer_class = TodoSerializer

class TodoRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
“””
检索、更新或删除一个 Todo 实例。
“””
queryset = Todo.objects.all()
serializer_class = TodoSerializer
“`

这段代码实现了与 APIView 示例完全相同的功能,但代码量大大减少。这就是 generics 视图的强大之处。

4.4 使用 ViewSetRouter (处理一组相关操作)

ViewSet 是一种更高级的抽象,它将一组相关的视图逻辑(如列表、创建、详情、更新、删除)打包到一个类中。结合 Router 可以自动生成 URL 模式,进一步简化 URL 配置。

“`python

todos/views.py (ViewSet 示例)

请注释掉或删除前面的所有视图示例代码,只保留此部分

from rest_framework import viewsets
from .models import Todo
from .serializers import TodoSerializer

class TodoViewSet(viewsets.ModelViewSet):
“””
允许用户查看、编辑和删除 Todo 实例的 API 视图集。
“””
queryset = Todo.objects.all()
serializer_class = TodoSerializer
“`

ModelViewSet 提供了完整的 create, retrieve, update, partial_update, destroylist 操作。

5. 配置 URL 路由

为了让您的 API 能够访问,我们需要将视图映射到 URL。

5.1 为 generics.*APIView 配置 URL

首先,在 todos 应用目录下创建 todos/urls.py 文件:

“`python

todos/urls.py

from django.urls import path
from .views import TodoListCreateAPIView, TodoRetrieveUpdateDestroyAPIView

urlpatterns = [
path(‘todos/’, TodoListCreateAPIView.as_view(), name=’todo-list-create’),
path(‘todos//’, TodoRetrieveUpdateDestroyAPIView.as_view(), name=’todo-detail’),
]
“`

然后,将 todos 应用的 URL 包含到项目的根 URL 配置中。打开 myapi_project/urls.py

“`python

myapi_project/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘todos.urls’)), # 将 todos 应用的 URL 包含进来
]
“`

5.2 为 ViewSetRouter 配置 URL (如果选择 ViewSet)

如果您选择使用 ViewSet,URL 配置会更加简单。

首先,删除 todos/urls.py 中为 generics.*APIView 配置的代码。

然后,修改 todos/urls.py 如下:

“`python

todos/urls.py (ViewSet 示例)

from rest_framework.routers import DefaultRouter
from .views import TodoViewSet

router = DefaultRouter()
router.register(r’todos’, TodoViewSet, basename=’todo’) # r’todos’ 是 URL 前缀

urlpatterns = router.urls
“`

DefaultRouter 会自动为 TodoViewSet 生成列表、详情等 URL 模式。basename 参数用于在 URL 名称中生成前缀,例如 todo-list, todo-detail

myapi_project/urls.py 的配置保持不变:

“`python

myapi_project/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘todos.urls’)), # 包含 todos 应用的 URL
]
“`

在本教程中,为了简洁和DRF的典型用法,我们推荐使用 generics.*APIViewViewSet。后续测试将基于 ViewSet 进行演示,因为其更为通用和强大。

6. 运行服务器并测试 API

现在,我们已经完成了 API 的基本搭建。运行 Django 开发服务器:

bash
python manage.py runserver

打开浏览器,访问 http://127.0.0.1:8000/api/todos/

您应该会看到 DRF 提供的可浏览 API 界面!这是一个非常方便的功能,允许您通过浏览器直接与 API 交互,进行 GET、POST、PUT、DELETE 等操作。

测试操作 (假设您使用了 TodoViewSet):

  • GET (获取所有 Todo):
    访问 http://127.0.0.1:8000/api/todos/。您应该会看到一个空的列表(因为还没有数据)。
  • POST (创建一个 Todo):
    在浏览器界面的底部,您会看到一个表单。填写 titledescriptioncompleted 可以选择或留空(默认为 False)。点击 POST。如果成功,您将看到新创建的 Todo 对象。
  • GET (获取单个 Todo):
    创建一些 Todo 后,访问 http://127.0.0.1:8000/api/todos/1/ (假设 id 为 1)。
  • PUT/PATCH (更新 Todo):
    访问 http://127.0.0.1:8000/api/todos/1/。在底部表单中修改数据,点击 PUT (完全替换) 或 PATCH (部分更新)。
  • DELETE (删除 Todo):
    访问 http://127.0.0.1:8000/api/todos/1/。点击 DELETE 按钮。

您也可以使用 curl 或 Postman/Insomnia 等工具进行测试。

使用 curl 示例:

“`bash

创建一个 Todo

curl -X POST -H “Content-Type: application/json” -d ‘{“title”: “学习 DRF”, “description”: “完成 DRF 教程的学习”, “completed”: false}’ http://127.0.0.1:8000/api/todos/

获取所有 Todo

curl http://127.0.0.1:8000/api/todos/

获取 ID 为 1 的 Todo

curl http://127.0.0.1:8000/api/todos/1/

更新 ID 为 1 的 Todo

curl -X PUT -H “Content-Type: application/json” -d ‘{“title”: “DRF 教程完成”, “description”: “已经完成了 DRF 教程的学习”, “completed”: true}’ http://127.0.0.1:8000/api/todos/1/

删除 ID 为 1 的 Todo

curl -X DELETE http://127.0.0.1:8000/api/todos/1/
“`

7. 认证与权限 (Authentication & Permissions)

目前我们的 API 是完全公开的,任何人都可以访问和修改数据。在实际项目中,这通常是不可接受的。DRF 提供了灵活的认证和权限系统来保护您的 API。

7.1 认证 (Authentication)

认证用于验证用户的身份。DRF 支持多种认证方案,如 SessionAuthentication (用于 Django 管理后台和可浏览 API)、TokenAuthenticationBasicAuthenticationOAuth2Authentication 等。

全局配置认证类:

myapi_project/settings.py 中添加或修改 REST_FRAMEWORK 配置:

“`python

myapi_project/settings.py

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
‘rest_framework.authentication.TokenAuthentication’, # 如果您想使用基于 Token 的认证
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’, # 默认只允许认证用户访问
],
}
“`

为了使用 TokenAuthentication,您需要安装 rest_framework.authtoken 应用:

“`python

myapi_project/settings.py

INSTALLED_APPS = [
# …
‘rest_framework’,
‘rest_framework.authtoken’, # 添加此行
‘todos’,
]
“`

并进行迁移:

bash
python manage.py makemigrations
python manage.py migrate

现在,如果您尝试访问 API,会发现需要登录。在可浏览 API 中,您可以登录 Django 管理员账户(如果您创建过)来继续操作。

7.2 权限 (Permissions)

权限用于确定经过认证的用户是否有权执行特定的操作。DRF 提供了 AllowAnyIsAuthenticatedIsAdminUserIsAuthenticatedOrReadOnly 等权限类。

视图级别配置权限:

您也可以在特定的视图上覆盖全局权限:

“`python

todos/views.py

from rest_framework.permissions import IsAdminUser, IsAuthenticatedOrReadOnly

… 其他导入 …

class TodoViewSet(viewsets.ModelViewSet):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
# permission_classes = [IsAdminUser] # 只有管理员用户可以完全操作
permission_classes = [IsAuthenticatedOrReadOnly] # 认证用户可读写,未认证用户只读
“`

8. 总结与展望

恭喜您!您已经成功地从零开始搭建了一个功能完善的 RESTful API,并了解了 DRF 的核心组件。

在本教程中,我们学习了:

  • DRF 的基本概念和优势。
  • 如何设置 Django 项目并集成 DRF。
  • 如何定义 Django 模型。
  • 如何使用序列化器将模型数据转换为 API 友好的格式。
  • 如何使用 APIViewGenericAPIViewViewSet 构建 API 视图。
  • 如何配置 URL 路由。
  • 如何通过可浏览 API 和 curl 测试 API。
  • 初步了解了 DRF 的认证和权限系统。

下一步您可以探索:

  • 过滤、搜索和排序: DRF 提供了强大的工具来处理这些常见的 API 需求。
  • 分页: 处理大量数据时必不可少。
  • 自定义字段和序列化器: 创建更复杂的序列化逻辑。
  • 限流 (Throttling): 控制客户端的请求频率。
  • 测试: 编写单元测试和集成测试来确保 API 的健壮性。
  • 部署: 将您的 API 部署到生产环境。
  • 更复杂的认证方案: 如 OAuth2。

Django REST Framework 是一个非常强大且灵活的工具,可以帮助您快速高效地构建高质量的 API。继续实践和探索,您将能够利用它来构建各种复杂的应用程序后端。

祝您编程愉快!


好的,我已经为您撰写了一篇详细描述“DRF 教程:从零开始搭建 RESTful API”的文章。请查阅。

滚动至顶部