使用 Django REST framework 构建 API:基础教程 – wiki基地


使用 Django REST framework 构建 API:基础教程

欢迎来到使用 Django REST framework (DRF) 构建 Web API 的世界!如果你是 Django 开发者,并且想要为你的前端应用、移动应用或其他服务提供数据接口,那么 DRF 无疑是你的最佳选择。它在 Django 的基础上提供了强大、灵活且易于使用的工具集,让你能够快速地构建出符合 RESTful 原则的 Web API。

本教程将从零开始,带你一步步构建一个简单的 API。我们将涵盖 DRF 的核心概念,包括序列化器 (Serializers)、视图 (Views) 的不同实现方式(函数、类、通用类、视图集)、URL 路由以及 DRF 提供的强大特性,如可浏览 API (Browsable API)。

我们将构建一个简单的“图书管理”API,允许用户查看、创建、更新和删除图书记录。

1. 什么是 API?为什么使用 Django REST framework?

在开始之前,我们先简单回顾一下基本概念。

API (Application Programming Interface):应用程序编程接口。在 Web 开发中,它通常指的是一套允许不同软件应用之间进行交互的规则和定义。Web API 通常使用 HTTP 协议作为传输方式,并常用 JSON 或 XML 格式来交换数据。通过 API,客户端(如浏览器、移动 App)可以向服务器请求数据或发送指令,而无需关心服务器端的具体实现细节。

为什么选择 Django?:Django 是一个成熟、功能齐全的 Python Web 框架。它提供了强大的 ORM (Object-Relational Mapper)、URL 路由、模板系统、认证系统以及便捷的管理后台。这些坚实的基础使得构建复杂的 Web 应用变得高效。

为什么选择 Django REST framework?:虽然你可以仅凭 Django 和一些 Python 库来构建 API,但这会非常繁琐。DRF 建立在 Django 之上,专门为构建 Web API 设计,它解决了许多构建 API 时遇到的常见问题,并提供了大量便利的工具:

  • 序列化器 (Serializers): 轻松地将 Django 模型或其他数据类型转换为 JSON、XML 等格式,反之亦然,同时处理数据验证。
  • 视图 (Views): 提供多种视图类型,从简单的函数视图到功能强大的通用类视图和视图集,极大地简化了 CRUD (Create, Read, Update, Delete) 操作的实现。
  • 认证与权限 (Authentication & Permissions): 内置多种认证(如 Token、Session、OAuth)和权限类,帮助你轻松保护 API。
  • 节流 (Throttling): 控制请求频率,防止滥用。
  • 过滤与排序 (Filtering & Ordering): 方便地为列表视图添加数据过滤和排序功能。
  • 分页 (Pagination): 轻松实现大型数据集的分页。
  • 可浏览 API (Browsable API): 一个基于 Web 的、非常友好的界面,方便开发者和测试人员查看和测试 API 端点。

简而言之,DRF 让你能够以更少、更优雅的代码快速构建出功能完备、易于维护的 Web API。

2. 环境准备与项目设置

在开始之前,请确保你的系统已安装 Python 和 pip。推荐使用虚拟环境来隔离项目依赖。

  1. 创建虚拟环境 (可选但强烈推荐):
    bash
    python -m venv venv

  2. 激活虚拟环境:

    • Windows: venv\Scripts\activate
    • macOS/Linux: source venv/bin/activate
  3. 安装 Django 和 Django REST framework:
    bash
    pip install Django djangorestframework

  4. 创建一个新的 Django 项目:
    bash
    django-admin startproject myapi .

    (这里的 . 表示在当前目录下创建项目文件)

  5. 创建一个新的 Django 应用:
    我们将创建一个名为 books 的应用来管理图书数据。
    bash
    python manage.py startapp books

  6. 将新创建的应用和 DRF 添加到 Django 项目的设置中:
    打开 myapi/settings.py 文件,找到 INSTALLED_APPS 列表,添加 'books.apps.BooksConfig''rest_framework'

    “`python

    myapi/settings.py

    INSTALLED_APPS = [
    ‘django.contrib.admin’,
    ‘django.contrib.auth’,
    ‘django.contrib.contenttypes’,
    ‘django.contrib.sessions’,
    ‘django.contrib.messages’,
    ‘django.contrib.staticfiles’,

    # 新增的应用
    'books.apps.BooksConfig',
    # 新增的 DRF
    'rest_framework',
    

    ]

    … 其他设置保持不变

    “`

  7. 运行数据库迁移: Django 需要创建一些默认的数据库表(用户、权限等)。
    bash
    python manage.py migrate

至此,你的项目基础结构已经搭建完毕。

3. 定义模型 (Models)

我们需要一个模型来存储图书数据。在 books/models.py 文件中定义一个简单的 Book 模型。

“`python

books/models.py

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
publication_date = models.DateField()

def __str__(self):
    return self.title

class Meta:
    ordering = ['-publication_date', 'title'] # 可选:设置默认排序

“`

保存文件后,运行数据库迁移命令来创建 Book 模型对应的数据库表:

bash
python manage.py makemigrations books
python manage.py migrate

现在,数据库中已经有了存储图书的表。

4. 序列化器 (Serializers)

序列化器是 DRF 中最核心的概念之一。它的主要作用有两个:

  1. 序列化 (Serialization): 将 Django 模型实例、QuerySet 或其他 Python 数据类型转换为可以轻松渲染成 JSON、XML 等格式的原始数据类型(如字典、列表)。
  2. 反序列化 (Deserialization): 将接收到的原始数据(如来自客户端的 JSON)转换回 Python 数据类型,并对数据进行验证。如果数据有效,还可以用于创建或更新模型实例。

我们将创建一个 BookSerializer 来处理 Book 模型的序列化和反序列化。在 books 应用目录下创建一个新的文件 serializers.py

“`python

books/serializers.py

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = [‘id’, ‘title’, ‘author’, ‘publication_date’]
# 或者使用 fields = ‘all‘ 包含所有字段,但明确列出字段通常更好
# read_only_fields = [‘id’] # id 字段通常是只读的
“`

这里我们使用了 serializers.ModelSerializer。这是 DRF 提供的一个非常方便的类,它可以自动地:

  • 根据指定的 modelfields 创建对应的序列化器字段。
  • 为包含所有模型字段的序列化器自动实现 create()update() 方法。

Meta 类中:
* model = Book 指明这个序列化器是为 Book 模型服务的。
* fields = [...] 列出了你希望在序列化和反序列化中包含的模型字段。我们包含了 id 字段,它通常作为资源的唯一标识符被客户端使用。

如果你不想手动列出所有字段,可以使用 fields = '__all__'。但请注意,这会包含模型中的所有字段,包括你可能不希望暴露给 API 的敏感字段。明确列出需要的字段是一个更好的实践。

5. 构建视图 (Views) – 函数视图 (Function-Based Views – FBVs)

视图处理 API 的请求和响应逻辑。DRF 提供了多种编写视图的方式,我们将从最基础的函数视图开始,逐步过渡到更高级的方式。

函数视图使用标准的 Django 函数视图语法,但利用 DRF 提供的 @api_view 装饰器来处理请求解析和响应渲染。

books/views.py 中编写函数视图:

“`python

books/views.py

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
from django.shortcuts import get_object_or_404 # 用于获取单个对象,如果不存在则返回404

@api_view([‘GET’, ‘POST’])
def book_list(request):
“””
列出所有图书,或创建一个新图书。
“””
if request.method == ‘GET’:
# 获取所有图书对象
books = Book.objects.all()
# 使用 BookSerializer 序列化 QuerySet (many=True 表示序列化多个对象)
serializer = BookSerializer(books, many=True)
# 返回 JSON 响应
return Response(serializer.data)

elif request.method == 'POST':
    # 使用 BookSerializer 反序列化请求数据
    serializer = BookSerializer(data=request.data)
    # 验证数据
    if serializer.is_valid():
        # 如果数据有效,保存新的图书对象
        serializer.save()
        # 返回新创建的对象数据和 201 Created 状态码
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    # 如果数据无效,返回错误信息和 400 Bad Request 状态码
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view([‘GET’, ‘PUT’, ‘DELETE’])
def book_detail(request, pk):
“””
检索、更新或删除一个图书实例。
“””
# 尝试获取指定 pk 的图书对象,如果不存在则返回 404
book = get_object_or_404(Book, pk=pk)

if request.method == 'GET':
    # 序列化单个图书对象
    serializer = BookSerializer(book)
    return Response(serializer.data)

elif request.method == 'PUT':
    # 使用 BookSerializer 反序列化请求数据并更新现有对象
    serializer = BookSerializer(book, data=request.data)
    if serializer.is_valid():
        serializer.save()
        # 返回更新后的对象数据
        return Response(serializer.data)
    # 如果数据无效,返回错误信息
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

elif request.method == 'DELETE':
    # 删除图书对象
    book.delete()
    # 返回 204 No Content 状态码,表示删除成功但没有内容返回
    return Response(status=status.HTTP_204_NO_CONTENT)

“`

解释:

  • @api_view(['GET', 'POST']): 这个装饰器包裹了标准的 Django 函数视图。它告诉 DRF 这个函数是一个 API 视图,并且只响应列出的 HTTP 方法。它还处理请求解析(将客户端发送的 JSON/XML 等解析为 request.data)和响应渲染(将 Response 对象中的数据渲染为 JSON/XML 等)。
  • request.data: DRF 的 Request 对象,类似于 Django 的 request.POSTrequest.FILES,但它能够处理多种媒体类型(如 JSON、表单数据)。
  • Response(): DRF 的 Response 对象,接收序列化后的数据,并负责渲染到最终的响应内容中(默认为 JSON)。你可以通过 status 参数设置 HTTP 状态码。
  • serializer.is_valid(): 调用序列化器的验证方法。这是反序列化(客户端发送数据到服务器)的关键步骤。如果数据与序列化器定义的字段类型和验证规则不符,is_valid() 返回 False,并且 serializer.errors 属性将包含详细的错误信息。
  • serializer.save(): 如果 is_valid() 返回 True,调用 save() 方法会根据验证后的数据创建一个新的模型实例(如果序列化器没有传入实例)或更新一个现有模型实例(如果序列化器传入了实例)。ModelSerializer 自动实现了这些逻辑。
  • status: DRF 提供的一个模块,包含了常用的 HTTP 状态码常量,提高了代码的可读性。
  • get_object_or_404(): 一个 Django 快捷函数,用于根据主键从数据库中获取对象,如果对象不存在,则自动抛出 Http404 异常,DRF 会将其转换为 404 Not Found 响应。

6. 配置 URL 路由 (URLs)

现在我们需要将这些视图映射到 URL。

首先,在 books 应用目录下创建一个 urls.py 文件。

“`python

books/urls.py

from django.urls import path
from . import views

urlpatterns = [
path(‘books/’, views.book_list, name=’book_list’),
path(‘books//’, views.book_detail, name=’book_detail’),
]
“`

然后,在项目的根 URL 配置文件 myapi/urls.py 中包含 books 应用的 URL。

“`python

myapi/urls.py

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

urlpatterns = [
path(‘admin/’, admin.site.urls),
# 将 books 应用的 URL 包含在 api/ 前缀下
path(‘api/’, include(‘books.urls’)),
]
“`

这样,我们的图书列表和创建 API 将在 /api/books/ 路径下,而单个图书的检索、更新和删除 API 将在 /api/books/<id>/ 路径下。

7. 测试 API (使用可浏览 API)

DRF 最令人称道的功能之一是其可浏览 API。它提供了一个友好的 Web 界面来查看和测试你的 API 端点。

  1. 启动 Django 开发服务器:
    bash
    python manage.py runserver

  2. 访问 URL: 打开浏览器,访问 http://127.0.0.1:8000/api/books/

    你应该会看到一个漂亮的网页界面,展示了当前 /api/books/ 端点支持的 HTTP 方法(GET, POST)。

    • GET 请求: 当你访问这个页面时,它会自动执行一个 GET 请求并显示结果(一个空的列表,因为我们还没有添加图书)。
    • POST 请求: 在页面下方,你会看到一个表单,允许你输入 JSON 数据来创建一个新的图书。尝试输入如下 JSON 数据:
      json
      {
      "title": "老人与海",
      "author": "欧内斯特·海明威",
      "publication_date": "1952-09-01"
      }

      点击 POST 按钮。如果成功,你会看到新创建的图书数据和一个 201 Created 状态码。
  3. 访问单个图书: 访问 http://127.0.0.1:8000/api/books/1/ (如果第一本书的 id 是 1)。

    你应该会看到单个图书的详细信息页面,以及支持的方法(GET, PUT, DELETE)。

    • GET 请求: 显示图书详情。
    • PUT 请求: 页面下方有表单,可以修改图书数据并提交。
    • DELETE 请求: 页面下方有 DELETE 按钮,可以删除图书。

这个可浏览 API 是开发和调试 API 的强大工具。

8. 构建视图 (Views) – 类视图 (Class-Based Views – CBVs)

虽然函数视图对于简单场景来说非常直观,但随着逻辑的复杂化,类视图提供了更好的组织结构和代码重用性。DRF 的 APIView 类是基于 Django 的 View 类构建的,但增加了 DRF 特有的功能(请求解析、响应渲染、认证、权限、节流等)。

我们将把之前的函数视图重写为类视图。修改 books/views.py

“`python

books/views.py (重写为类视图)

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404
from .models import Book
from .serializers import BookSerializer

class BookList(APIView):
“””
列出所有图书,或创建一个新图书。
“””
def get(self, request, format=None):
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data)

def post(self, request, format=None):
    serializer = BookSerializer(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 BookDetail(APIView):
“””
检索、更新或删除一个图书实例。
“””
# 定义一个 helper 方法来获取对象,避免在每个 HTTP 方法中重复
def get_object(self, pk):
return get_object_or_404(Book, pk=pk)

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

def put(self, request, pk, format=None):
    book = self.get_object(pk)
    serializer = BookSerializer(book, 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):
    book = self.get_object(pk)
    book.delete()
    return Response(status=status.HTTP_204_NO_CONTENT)

“`

解释:

  • 我们不再使用 @api_view 装饰器,而是直接继承 APIView
  • 不同的 HTTP 方法 (GET, POST, PUT, DELETE) 被实现为类中的同名方法。
  • 这些方法接收 request 对象作为第一个参数,以及从 URL 捕获的关键字参数(如 pk)。format=None 参数用于处理请求格式(这里我们不深究,保留默认即可)。
  • 逻辑与函数视图中的基本相同,只是组织方式不同。

更新 books/urls.py 以使用类视图的 .as_view() 方法:

“`python

books/urls.py (使用类视图)

from django.urls import path
from .views import BookList, BookDetail # 从 views 导入类视图

urlpatterns = [
path(‘books/’, BookList.as_view(), name=’book_list’),
path(‘books//’, BookDetail.as_view(), name=’book_detail’),
]
“`

重新启动服务器,可浏览 API 应该仍然按预期工作,但现在你的视图代码组织得更好了。

9. 构建视图 (Views) – 通用类视图 (Generic Class-Based Views)

编写 APIView 类视图虽然比函数视图结构化,但对于常见的 API 模式(如列出/创建、检索/更新/删除)仍然需要编写重复的代码(如获取 QuerySet、实例化序列化器、检查 is_valid()、调用 save()、返回响应)。

DRF 提供了一套强大的通用类视图,它们是 APIView 的子类,预先实现了这些常见模式。你只需要通过设置一些属性(如 querysetserializer_class)就可以快速构建出功能完备的 API 视图。

常见的通用视图包括:
* CreateAPIView: 只支持 POST (创建)
* ListAPIView: 只支持 GET (列出)
* RetrieveAPIView: 只支持 GET (检索单个)
* UpdateAPIView: 只支持 PUT/PATCH (更新单个)
* DestroyAPIView: 只支持 DELETE (删除单个)
* ListCreateAPIView: 支持 GET (列出) 和 POST (创建)
* RetrieveUpdateAPIView: 支持 GET (检索)、PUT (更新) 和 PATCH
* RetrieveDestroyAPIView: 支持 GET (检索) 和 DELETE
* RetrieveUpdateDestroyAPIView: 支持 GET (检索)、PUT、PATCH 和 DELETE

我们将使用 ListCreateAPIViewRetrieveUpdateDestroyAPIView 来进一步简化我们的视图代码。修改 books/views.py

“`python

books/views.py (重写为通用类视图)

导入通用的 API 视图

from rest_framework import generics
from .models import Book
from .serializers import BookSerializer

class BookList(generics.ListCreateAPIView):
“””
列出所有图书,或创建一个新图书。
“””
# 定义要操作的 QuerySet
queryset = Book.objects.all()
# 定义用于序列化和反序列化的序列化器类
serializer_class = BookSerializer

class BookDetail(generics.RetrieveUpdateDestroyAPIView):
“””
检索、更新或删除一个图书实例。
“””
# 定义要操作的 QuerySet (通用视图会自动从 QuerySet 中根据 URL 参数过滤出单个对象)
queryset = Book.objects.all()
# 定义用于序列化和反序列化的序列化器类
serializer_class = BookSerializer
# lookup_field = ‘pk’ # 默认就是 ‘pk’,如果你的 URL 参数是其他名字,需要指定
“`

解释:

  • 代码变得极其简洁!我们不再需要手动编写 get(), post(), put(), delete() 方法中的大部分逻辑。
  • 通过简单地设置 queryset 属性,通用视图知道如何获取对象列表或单个对象。
  • 通过设置 serializer_class 属性,通用视图知道使用哪个序列化器来序列化/反序列化数据。
  • ListCreateAPIView 自动实现了列出 (GET) 和创建 (POST) 的逻辑。
  • RetrieveUpdateDestroyAPIView 自动实现了检索 (GET)、更新 (PUT/PATCH) 和删除 (DELETE) 的逻辑。它会根据 URL 中的 pk 参数(默认 lookup_field 就是 pk)从 queryset 中获取单个对象。

books/urls.py 文件保持不变,因为它仍然使用 .as_view() 方法将类视图映射到 URL。

“`python

books/urls.py (通用类视图 URL 配置,与类视图一样)

from django.urls import path
from .views import BookList, BookDetail # 从 views 导入通用类视图

urlpatterns = [
path(‘books/’, BookList.as_view(), name=’book_list’),
path(‘books//’, BookDetail.as_view(), name=’book_detail’),
]
“`

重新启动服务器,再次访问可浏览 API。功能与之前完全相同,但你的代码现在更加精简和符合 DRF 的习惯用法。通用视图是构建标准 CRUD API 的首选方式。

10. 构建视图 (Views) – 视图集 (ViewSets) 与路由器 (Routers)

随着 API 端点数量的增加,手动在 urls.py 中定义每个 URL 模式会变得重复和繁琐。视图集 (ViewSets) 解决了这个问题,它们将与一个模型或一组相关资源相关的逻辑(list, create, retrieve, update, destroy)捆绑到一个类中。

路由器 (Routers) 则可以根据视图集自动生成 URL 模式,进一步简化 URL 配置。

我们将使用 ModelViewSet,它是 DRF 提供的一个通用视图集,它继承了所有通用视图的行为(List, Create, Retrieve, Update, Destroy)。

修改 books/views.py

“`python

books/views.py (重写为视图集)

导入视图集和通用视图集

from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
“””
提供了对 Book 模型的 ‘list’, ‘create’, ‘retrieve’, ‘update’, ‘partial_update’, ‘destroy’ 操作。
“””
queryset = Book.objects.all()
serializer_class = BookSerializer
# lookup_field = ‘pk’ # 默认就是 ‘pk’
“`

解释:

  • 我们创建了一个 BookViewSet 继承自 viewsets.ModelViewSet
  • 同样只需要设置 querysetserializer_class 属性。
  • ModelViewSet 自动提供了对应 list, create, retrieve, update, partial_update, destroy (以及对应的 HTTP 方法 GET/POST/PUT/PATCH/DELETE) 的方法实现。

现在修改 books/urls.pymyapi/urls.py 来使用路由器。

修改 books/urls.py

“`python

books/urls.py (使用路由器)

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet # 导入视图集

创建一个路由器实例

router = DefaultRouter()

注册视图集到路由器

第一个参数是 URL 前缀 (basename),将生成如 /books/ 和 /books/{pk}/ 的 URL

第二个参数是视图集类

basename 参数是必需的,除非 queryset 属性有 .model 属性

router.register(r’books’, BookViewSet)

路由器会自动生成 URL 模式,我们只需要将这些模式包含到 urlpatterns 中

urlpatterns = [
path(”, include(router.urls)),
]
“`

修改 myapi/urls.py (保持不变,因为我们在 myapi/urls.py 中已经包含了 books.urls):

“`python

myapi/urls.py (保持不变)

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

urlpatterns = [
path(‘admin/’, admin.site.urls),
# 将 books 应用的 URL 包含在 api/ 前缀下
path(‘api/’, include(‘books.urls’)), # books.urls 现在使用了路由器
]
“`

重新启动服务器,再次访问 http://127.0.0.1:8000/api/

你现在应该会看到 DRF 的 Root API 页面,列出了路由器生成的 URL 端点 (http://127.0.0.1:8000/api/books/)。点击这个链接,你会被带到图书列表/创建的可浏览 API 页面,与之前的功能完全一致。访问单个图书端点 http://127.0.0.1:8000/api/books/1/ 也同样工作。

视图集和路由器是构建大型 API 的推荐方式,它们极大地减少了视图和 URL 配置的代码量。

11. 基础认证与权限 (Authentication & Permissions)

构建一个实际的 API 几乎总需要考虑安全问题,即谁可以访问哪些资源以及执行哪些操作。DRF 提供了强大的认证和权限系统。

  • 认证 (Authentication): 确定请求的来源(即用户是谁)。例如,Token 认证、Session 认证、OAuth2 等。
  • 权限 (Permissions): 确定经过认证的用户是否被允许执行请求的操作。例如,IsAuthenticated (必须登录)、IsAdminUser (必须是管理员)、AllowAny (允许所有人)、IsAuthenticatedOrReadOnly (登录用户可写,未登录用户只读) 等。

在这里,我们只添加一个简单的权限示例:只允许经过认证的用户创建、更新和删除图书,未认证用户只能查看。

修改 books/views.py 中的 BookViewSet

“`python

books/views.py (添加权限)

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly # 导入权限类
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
“””
提供了对 Book 模型的 ‘list’, ‘create’, ‘retrieve’, ‘update’, ‘partial_update’, ‘destroy’ 操作。
“””
queryset = Book.objects.all()
serializer_class = BookSerializer
# 添加权限类
permission_classes = [IsAuthenticatedOrReadOnly]
“`

解释:

  • permission_classes = [IsAuthenticatedOrReadOnly]: 这个属性指定了应用于此视图集的权限类列表。DRF 会依次检查列表中的所有权限类。
  • IsAuthenticatedOrReadOnly: 这个内置权限类允许任何用户对资源执行安全的读操作(GET, HEAD, OPTIONS),但只有经过认证的用户才能执行写操作(POST, PUT, PATCH, DELETE)。

现在,如果你在可浏览 API 中尝试在未登录状态下 POST 创建图书,会收到 403 Forbidden 错误。尝试 PUT 或 DELETE 单个图书也会收到同样的错误。但是 GET 请求仍然会成功。

要测试认证后的行为,你可以创建一个用户(使用 python manage.py createsuperuser)并通过 DRF 提供的认证方式(如 Session 认证,因为我们默认开启了 Django 的 Session 中间件)登录管理后台。然后,在同一个浏览器会话中访问可浏览 API,你就可以执行写操作了。对于实际的 API 客户端(如移动 App),你通常会使用 Token 认证或其他无状态认证方式。

全局默认权限: 你也可以在 settings.py 中设置全局的默认认证和权限类:

“`python

myapi/settings.py

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
‘rest_framework.authentication.BasicAuthentication’,
# ‘rest_framework.authentication.TokenAuthentication’, # 如果你安装了 rest_framework.authtoken 并运行了迁移
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’, # 例如,默认所有 API 都需要认证
# ‘rest_framework.permissions.AllowAny’, # 默认允许所有访问
],
# … 其他 DRF 设置
}
``
在视图集中设置的
permission_classes` 会覆盖全局设置。

12. 序列化器的高级用法 (简述)

ModelSerializer 已经非常强大,但有时你需要更多的控制:

  • 自定义字段: 可以添加不在模型中的字段,或者修改模型字段的行为(例如,使用 SerializerMethodField 计算一个值)。
  • 字段选项: 控制字段的 read_only, write_only, required 等属性。
  • 验证: 除了模型自带的验证,可以在序列化器层面添加额外的字段验证 (validate_field) 或对象级别验证 (validate)。
  • 嵌套序列化器: 当模型之间存在关系时(如 ForeignKey),可以将关联模型的序列化器嵌套进来,以表示关联数据。

例如,假设你想在图书详情中包含作者的姓名而不是 ID,并且作者模型是另一个模型,你可以创建 AuthorSerializer 并将其嵌套在 BookSerializer 中。

“`python

books/serializers.py (自定义示例)

class BookSerializer(serializers.ModelSerializer):
# read_only=True 表示这个字段只在序列化时包含,反序列化时忽略
id = serializers.IntegerField(read_only=True)

class Meta:
    model = Book
    fields = ['id', 'title', 'author', 'publication_date']

# 示例:添加一个只读字段来表示图书的年代
year_published = serializers.SerializerMethodField()

def get_year_published(self, obj):
    # obj 是当前的 Book 实例
    return obj.publication_date.year if obj.publication_date else None

# 示例:自定义字段验证
def validate_title(self, value):
    if len(value) < 3:
        raise serializers.ValidationError("图书标题太短!")
    return value

# 示例:对象级别验证 (例如,确保出版日期不是未来)
def validate(self, data):
    from django.utils import timezone
    if 'publication_date' in data and data['publication_date'] > timezone.now().date():
         raise serializers.ValidationError({"publication_date": "出版日期不能在未来!"})
    return data

“`
通过这种方式,你可以精细地控制 API 的输入和输出格式以及数据验证逻辑。

13. 总结与下一步

恭喜你!你已经完成了 Django REST framework 基础教程的学习。我们从零开始,定义了模型,创建了序列化器,并逐步学习了使用函数视图、类视图、通用类视图和视图集/路由器来构建 API 端点。你还了解了 DRF 的可浏览 API 以及基础的认证和权限概念。

现在你已经掌握了使用 DRF 构建基础 API 的核心技能。要进一步提升,你可以继续学习以下主题:

  • 更深入的认证方式: Token 认证、JWT (JSON Web Tokens) 认证等。
  • 自定义权限: 创建自己的权限类来满足复杂的业务逻辑。
  • 过滤 (Filtering): 允许客户端通过 URL 参数过滤列表数据(如 /api/books/?author=Hemingway)。
  • 搜索 (Searching): 允许客户端进行文本搜索。
  • 分页 (Pagination): 处理大量数据的分批返回。
  • 版本控制 (Versioning): 管理 API 的不同版本。
  • 测试: 编写自动化测试来确保 API 的稳定性和正确性。
  • 文档: 使用 Swagger/OpenAPI 工具自动生成 API 文档。
  • 部署: 将你的 Django/DRF 项目部署到生产环境。

Django REST framework 是一个强大而灵活的工具。通过不断实践和深入学习其更多特性,你将能够构建出高质量、高性能的 Web API 来驱动你的应用。

希望这篇详细教程对你有所帮助!现在就开始动手,在你自己的项目中使用 DRF 吧!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部