71·模块十三:Web开发基础高级

使用 Django REST framework 构建 API

djangorest-frameworkapi

第71课:使用 Django REST framework 构建 API

所属模块:模块十三:Web开发基础
难度:Advanced
标签django, rest-framework, api
上一课:Django 用户认证系统
下一课:数据库基础:SQLite 与 Python


1. 学习目标

完成本课后,你将能够:

  1. 理解 RESTful API 的基本概念以及 Django REST framework (DRF) 的核心价值。
  2. 掌握使用 DRF 的 Serializer(序列化器)将 Django 模型实例与 JSON 数据相互转换。
  3. 学会使用 DRF 的 ViewSetRouter 快速定义 API 的视图逻辑与 URL 路由。
  4. 熟悉 API 中的分页与基本的权限配置。
  5. 独立创建并测试一个完整的 Django REST API。

2. 核心概念

2.1 什么是 RESTful API?

想象一下,你在一家餐厅。服务员(API)拿着菜单(请求)去厨房(服务器),然后将做好的菜(响应)端给你。REST 是一套设计原则,它规定了这个"服务员"应该如何行动:使用标准的 HTTP 动词(GET, POST, PUT, DELETE)来操作资源(比如"图书"、"用户"),并返回结构化的数据(通常是 JSON)。

Django REST framework (DRF) 就是 Django 框架里,专门用来打造这种高效、规范"服务员"的强大工具包。

2.2 核心组件

  • Serializer(序列化器):它是数据的"翻译官"和"守门员"。负责:
    1. 序列化:将复杂的 Django 模型实例(如 Book 对象)转换为 Python 字典,进而渲染成 JSON 字符串。
    2. 反序列化:将客户端发来的 JSON 数据(字典)验证、转换并保存为 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 浏览界面,你可以直接在页面上:

  1. 查看 JSON 格式的图书列表。
  2. 点击 "POST" 按钮,填写表单数据添加新图书。
  3. 点击某个图书的链接进入详情页,进行编辑或删除。

你也可以使用 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:基础序列化 (简单)

  1. books/models.py 中为 Book 模型添加一个 pages(页数,PositiveIntegerField)字段。
  2. 更新 BookSerializer,使其能序列化和反序列化这个新字段。
  3. 迁移数据库并测试 API,确保新字段出现在响应中,且创建图书时可以指定页数。

练习 2:自定义视图逻辑 (中等)

  1. BookViewSet 中添加一个自定义的 action。该 action 应该能返回所有价格低于 30 元的图书列表。
  • 使用 @action(detail=False, methods=['get']) 装饰器。
  • URL 端点应为 /api/books/cheap/
  1. 测试这个新端点。

练习 3:分页与认证 (挑战)

  1. 在项目的 settings.py 中为 DRF 配置全局分页。例如,设置每页显示 2 项记录。
    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 2
    }
    
  2. BookViewSet 的权限类设置为 IsAuthenticatedOrReadOnly(匿名用户只能读取,认证用户可以写入)。
  3. 重启服务器,测试分页效果。尝试以匿名用户身份创建图书(应失败),然后通过 Django Admin 或 Basic Auth 登录后再尝试。

5. 常见错误

  1. 忘记在 INSTALLED_APPS 中添加 'rest_framework':会导致 ModuleNotFoundError: No module named 'rest_framework'
  2. 序列化器 fields 列表包含不存在的字段:会在启动时报 Field name ... is not valid for model 错误。请检查字段名是否与模型完全一致。
  3. 视图集的 queryset 为空或配置错误:API 会返回空列表或 404 错误。确保 queryset = Book.objects.all() 已正确定义。
  4. 路由注册错误:如果 router.register(r'books', BookViewSet) 中的前缀写错,生成的 URL 就不符合预期。使用 DefaultRouterAPI Root 视图(通常在项目根 /api/)来检查注册情况。
  5. 未处理 CORS 问题:如果前端(如 React/Vue)和后端不在同一个域名/端口下,浏览器会因同源策略阻止请求。需要安装 django-cors-headers 应用来解决。

6. 小结

本节课我们深入学习了如何使用 Django REST framework 构建 API:

  1. RESTful 架构:我们了解了通过标准的 HTTP 方法操作资源的设计哲学。
  2. 核心三件套
    • Serializer:负责数据的验证与转换(模型 <-> JSON)。
    • ViewSet:集中定义了针对资源的增删改查业务逻辑。
    • Router:自动、规范地将 ViewSet 映射到 URL 路径。
  3. 快速开发:DRF 极大地简化了 API 的开发流程。通过继承 ModelViewSet 和使用 ModelSerializer,我们几乎不用编写样板代码就能获得完整的 CRUD 功能。
  4. 功能扩展:我们初步接触了如何添加自定义 action、配置分页和权限,让 API 更加强大和安全。

掌握 Django REST framework,意味着你拥有了快速将 Django 项目"后端服务化"的能力,为构建前后端分离的现代 Web 应用或移动 App 后台奠定了坚实基础。下一课,我们将回归基础,深入探讨数据库操作的核心——SQLite 与 Python。

练习编辑器

python
Loading...

继续学习

完成本课后,建议继续学习下一课「数据库基础:SQLite 与 Python」 以巩固所学知识。