第71课:使用 Django REST framework 构建 API
所属模块:模块十三:Web开发基础
难度:Advanced
标签:django, rest-framework, api
上一课:Django 用户认证系统
下一课:数据库基础:SQLite 与 Python
1. 学习目标
完成本课后,你将能够:
- 理解 RESTful API 的基本概念以及 Django REST framework (DRF) 的核心价值。
- 掌握使用 DRF 的
Serializer(序列化器)将 Django 模型实例与 JSON 数据相互转换。 - 学会使用 DRF 的
ViewSet和Router快速定义 API 的视图逻辑与 URL 路由。 - 熟悉 API 中的分页与基本的权限配置。
- 独立创建并测试一个完整的 Django REST API。
2. 核心概念
2.1 什么是 RESTful API?
想象一下,你在一家餐厅。服务员(API)拿着菜单(请求)去厨房(服务器),然后将做好的菜(响应)端给你。REST 是一套设计原则,它规定了这个"服务员"应该如何行动:使用标准的 HTTP 动词(GET, POST, PUT, DELETE)来操作资源(比如"图书"、"用户"),并返回结构化的数据(通常是 JSON)。
Django REST framework (DRF) 就是 Django 框架里,专门用来打造这种高效、规范"服务员"的强大工具包。
2.2 核心组件
- Serializer(序列化器):它是数据的"翻译官"和"守门员"。负责:
- 序列化:将复杂的 Django 模型实例(如
Book对象)转换为 Python 字典,进而渲染成 JSON 字符串。 - 反序列化:将客户端发来的 JSON 数据(字典)验证、转换并保存为 Django 模型实例。
- 序列化:将复杂的 Django 模型实例(如
- ViewSet(视图集):它是业务逻辑的"集合点"。它将一系列相关的视图逻辑(如列表、创建、详情、更新、删除)组合在一个类中,避免了大量重复的函数定义。
- Router(路由器):它是 URL 的"交通警察"。它能自动根据
ViewSet生成符合 RESTful 规范的 URL 模式(如/books/,/books/{id}/)。
2.3 一个简单的例子:图书 API
我们将构建一个管理"图书"资源的 API。
GET /api/books/-> 获取所有图书列表POST /api/books/-> 添加一本新图书GET /api/books/1/-> 获取 ID 为 1 的图书详情PUT /api/books/1/-> 更新 ID 为 1 的图书信息DELETE /api/books/1/-> 删除 ID 为 1 的图书
3. 代码示例
我们将基于一个已存在的 Django 项目 (myproject) 进行开发。
第1步:安装与设置
# 安装 Django REST framework
pip install djangorestframework
在项目的 settings.py 文件中,将 rest_framework 添加到 INSTALLED_APPS。
# myproject/settings.py
INSTALLED_APPS = [
...
'rest_framework',
'books', # 假设我们的图书应用叫 books
]
第2步:定义模型 (books/models.py)
# books/models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return f"{self.title} by {self.author}"
class Meta:
ordering = ['-published_date'] # 默认按出版日期倒序排列
运行迁移命令创建数据库表:python manage.py makemigrations books && python manage.py migrate
第3步:创建序列化器 (books/serializers.py)
# books/serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author', 'published_date', 'isbn', 'price'] # 明确指定要暴露的字段
第4步:创建视图集 (books/views.py)
# books/views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
"""
一个为 `Book` 模型提供完整 CRUD 操作的 ViewSet。
`ModelViewSet` 会自动提供 `list`, `create`, `retrieve`, `update`, `partial_update`, `destroy` 方法。
"""
queryset = Book.objects.all() # 指定该视图集要操作的数据集
serializer_class = BookSerializer # 指定使用的序列化器
# permission_classes = [permissions.IsAuthenticatedOrReadOnly] # 可选:设置权限
第5步:配置路由 (books/urls.py 和项目主 urls.py)
首先在 books 应用下创建 urls.py:
# books/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
# 创建一个路由器并注册我们的 ViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet) # `r'books'` 是 URL 的前缀
urlpatterns = [
path('', include(router.urls)),
]
然后在项目主 urls.py 中包含它:
# myproject/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('books.urls')), # 将所有图书 API 路由放在 /api/ 前缀下
]
第6步:启动服务器并测试
python manage.py runserver
现在,你可以通过浏览器访问 http://127.0.0.1:8000/api/books/。DRF 提供了一个强大的 Web 浏览界面,你可以直接在页面上:
- 查看 JSON 格式的图书列表。
- 点击 "POST" 按钮,填写表单数据添加新图书。
- 点击某个图书的链接进入详情页,进行编辑或删除。
你也可以使用 curl 或 Postman 等工具进行 API 测试。
# 使用 curl 获取图书列表
curl http://127.0.0.1:8000/api/books/
# 使用 curl 添加一本新图书
curl -X POST http://127.0.0.1:8000/api/books/ \
-H "Content-Type: application/json" \
-d '{"title":"新书标题", "author":"作者名", "published_date":"2023-10-01", "isbn":"9787111556787", "price":"49.99"}'
4. 实践练习
练习 1:基础序列化 (简单)
- 在
books/models.py中为Book模型添加一个pages(页数,PositiveIntegerField)字段。 - 更新
BookSerializer,使其能序列化和反序列化这个新字段。 - 迁移数据库并测试 API,确保新字段出现在响应中,且创建图书时可以指定页数。
练习 2:自定义视图逻辑 (中等)
- 在
BookViewSet中添加一个自定义的action。该 action 应该能返回所有价格低于 30 元的图书列表。
- 使用
@action(detail=False, methods=['get'])装饰器。 - URL 端点应为
/api/books/cheap/。
- 测试这个新端点。
练习 3:分页与认证 (挑战)
- 在项目的
settings.py中为 DRF 配置全局分页。例如,设置每页显示 2 项记录。REST_FRAMEWORK = { 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 2 } - 将
BookViewSet的权限类设置为IsAuthenticatedOrReadOnly(匿名用户只能读取,认证用户可以写入)。 - 重启服务器,测试分页效果。尝试以匿名用户身份创建图书(应失败),然后通过 Django Admin 或 Basic Auth 登录后再尝试。
5. 常见错误
- 忘记在
INSTALLED_APPS中添加'rest_framework':会导致ModuleNotFoundError: No module named 'rest_framework'。 - 序列化器
fields列表包含不存在的字段:会在启动时报Field name ... is not valid for model错误。请检查字段名是否与模型完全一致。 - 视图集的
queryset为空或配置错误:API 会返回空列表或 404 错误。确保queryset = Book.objects.all()已正确定义。 - 路由注册错误:如果
router.register(r'books', BookViewSet)中的前缀写错,生成的 URL 就不符合预期。使用DefaultRouter的API Root视图(通常在项目根/api/)来检查注册情况。 - 未处理 CORS 问题:如果前端(如 React/Vue)和后端不在同一个域名/端口下,浏览器会因同源策略阻止请求。需要安装
django-cors-headers应用来解决。
6. 小结
本节课我们深入学习了如何使用 Django REST framework 构建 API:
- RESTful 架构:我们了解了通过标准的 HTTP 方法操作资源的设计哲学。
- 核心三件套:
- Serializer:负责数据的验证与转换(模型 <-> JSON)。
- ViewSet:集中定义了针对资源的增删改查业务逻辑。
- Router:自动、规范地将 ViewSet 映射到 URL 路径。
- 快速开发:DRF 极大地简化了 API 的开发流程。通过继承
ModelViewSet和使用ModelSerializer,我们几乎不用编写样板代码就能获得完整的 CRUD 功能。 - 功能扩展:我们初步接触了如何添加自定义 action、配置分页和权限,让 API 更加强大和安全。
掌握 Django REST framework,意味着你拥有了快速将 Django 项目"后端服务化"的能力,为构建前后端分离的现代 Web 应用或移动 App 后台奠定了坚实基础。下一课,我们将回归基础,深入探讨数据库操作的核心——SQLite 与 Python。