学习 Django REST Framework:快速构建高效 RESTful API – wiki大全


学习 Django REST Framework:快速构建高效 RESTful API

在当今互联互通的世界中,API(应用程序接口)扮演着至关重要的角色,它们是不同软件系统之间进行数据交换和通信的桥梁。RESTful API 因其轻量级、无状态和易于理解的特性,成为了构建现代 Web 服务的主流选择。对于 Python 和 Django 开发者而言,Django REST Framework (DRF) 无疑是构建强大而高效的 RESTful API 的首选工具。

本文将深入探讨 Django REST Framework 的核心概念、快速入门指南,以及如何利用其高级功能来构建既高效又安全的 API。

1. 引言:为何选择 Django REST Framework?

Django 以其“电池包含在内”的哲学,为 Web 开发提供了全面的解决方案。然而,当我们需要构建一个独立的 API 层,而非传统的服务器端渲染应用时,Django 本身在 API 构造方面显得有些力不从心。这时,Django REST Framework 应运而生,它是一个强大且灵活的工具包,在 Django 的基础上,提供了丰富的功能来简化 RESTful API 的开发:

  • 易用性: 提供强大的序列化器,可以轻松地将 Django 模型序列化为 JSON/XML 等格式,并反序列化回模型实例。
  • 浏览式 API: 内置可浏览的 API 界面,极大地提高了开发和测试的便利性。
  • 丰富的功能: 提供认证、权限、限流、过滤、分页、版本控制等多种开箱即用的功能。
  • 高度可定制: 允许开发者根据需求轻松地扩展和定制各个组件。
  • 高效性: 提供了多种工具和模式,帮助开发者构建高性能的 API。

通过学习 DRF,您将能够以更快的速度、更高的效率构建出符合行业标准的 RESTful API。

2. DRF 核心概念

理解 DRF 的核心组件是高效使用的关键。

2.1 序列化器 (Serializers)

序列化器是 DRF 的核心概念之一,它们的功能是将复杂的数据类型(如 Django 模型实例或查询集)转换为原生 Python 数据类型,然后可以轻松地将其渲染为 JSON、XML 或其他内容类型。反之,它们也可以将传入的原生数据解析回复杂类型。

  • Serializer 最基础的序列化器类,适用于需要完全手动控制字段的情况。
  • ModelSerializer 继承自 Serializer,提供了与 Django 模型紧密集成的便利。它可以自动根据模型字段生成序列化器字段,并提供默认的 create()update() 方法,极大地简化了开发。

示例 (snippets/serializers.py):

“`python
from rest_framework import serializers
from snippets.models import Snippet
from django.contrib.auth.models import User

class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source=’owner.username’) # 添加只读字段

class Meta:
    model = Snippet
    fields = ['id', 'title', 'code', 'linenos', 'language', 'style', 'owner']

class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

class Meta:
    model = User
    fields = ['id', 'username', 'snippets']

“`

2.2 视图 (Views)

DRF 的视图负责处理传入的 HTTP 请求,并返回相应的 HTTP 响应。它在 Django 的 View 类的基础上进行了扩展,提供了更适用于 API 的抽象层。

  • APIView DRF 提供的基础视图类,比 Django 的 View 提供了更多的 API 特定功能,如请求解析、响应渲染和认证/权限处理。
  • GenericAPIView APIView 的扩展,提供了常用的方法,如 get_object()get_queryset()get_serializer(),适用于处理单一模型实例或列表。
  • 通用视图 (Generic Views): 针对常见的 API 模式(如列表、详情、创建、更新、删除)提供了预先构建的类。例如 ListAPIViewRetrieveAPIViewCreateAPIViewUpdateAPIViewDestroyAPIView 以及它们的组合 ListCreateAPIViewRetrieveUpdateDestroyAPIView 等。它们极大地减少了样板代码。
  • 视图集 (ViewSets): ViewSet 提供了更加抽象的视图定义方式,将一组相关操作(如 list, retrieve, create, update, destroy)集中到一个类中。结合路由 (Routers) 使用,可以自动生成 URL 模式,进一步简化 URL 配置。ModelViewSet 是最常用的视图集,直接与 Django 模型关联。

示例 (snippets/views.py):

“`python
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics, viewsets
from django.contrib.auth.models import User
from rest_framework import permissions

使用通用视图

class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly] # 添加权限控制

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)

class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]

使用 ViewSet (更简洁)

class UserViewSet(viewsets.ReadOnlyModelViewSet): # 提供 list 和 retrieve 方法
queryset = User.objects.all()
serializer_class = UserSerializer

如果 Snippet 也使用 ViewSet,代码会更简洁

class SnippetViewSet(viewsets.ModelViewSet):

queryset = Snippet.objects.all()

serializer_class = SnippetSerializer

permission_classes = [permissions.IsAuthenticatedOrReadOnly]

def perform_create(self, serializer):

serializer.save(owner=self.request.user)

“`

2.3 路由 (Routers)

路由是 DRF 的另一个强大特性,尤其是在使用 ViewSet 时。它们会自动为视图集生成 URL 模式,从而避免了手动编写大量的 URL 配置。

  • DefaultRouter 最常用的路由,它会自动为 ViewSet 生成标准的列表和详情 URL。

示例 (tutorial/urls.pysnippets/urls.py):

“`python

snippets/urls.py (当不使用 ViewSet 和 Router 时)

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
path(‘snippets/’, views.SnippetList.as_view()),
path(‘snippets//’, views.SnippetDetail.as_view()),
path(‘users/’, views.UserList.as_view()),
path(‘users//’, views.UserDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns) # 支持 .json/.api 后缀

tutorial/urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter # 引入 DefaultRouter
from snippets.views import SnippetViewSet, UserViewSet # 假设使用了 ViewSet

router = DefaultRouter()
router.register(r’snippets’, SnippetViewSet) # 注册 Snippet 视图集
router.register(r’users’, UserViewSet) # 注册 User 视图集

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(router.urls)), # 包含路由生成的 URL
path(‘api-auth/’, include(‘rest_framework.urls’)), # 用于 browsable API 的登录/登出
]
“`

3. 快速入门:构建你的第一个 DRF API

现在,让我们通过一个简单的例子,快速体验如何使用 DRF 构建一个 API。我们将创建一个管理代码片段 (Snippet) 的 API。

步骤 1:环境搭建与安装

首先,确保您已安装 Python 和 pip。建议使用虚拟环境:

“`bash

创建虚拟环境

python -m venv venv

激活虚拟环境 (Windows)

.\venv\Scripts\activate

激活虚拟环境 (macOS/Linux)

source venv/bin/activate

安装 Django 和 Django REST Framework

pip install Django djangorestframework
“`

步骤 2:创建 Django 项目和应用

“`bash

创建 Django 项目

django-admin startproject tutorial . # 注意末尾的 . 表示在当前目录创建项目

创建应用

python manage.py startapp snippets
“`

步骤 3:配置 settings.py

打开 tutorial/settings.py,将 'rest_framework''snippets' 添加到 INSTALLED_APPS 中:

“`python

tutorial/settings.py

INSTALLED_APPS = [
# … 其他应用 …
‘rest_framework’,
‘snippets’,
]
“`

步骤 4:定义模型 (snippets/models.py)

“`python
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles

LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted([(item, item) for item in get_all_styles()])

class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default=”)
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default=’python’, max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default=’friendly’, max_length=100)
owner = models.ForeignKey(‘auth.User’, related_name=’snippets’, on_delete=models.CASCADE, null=True) # 添加所有者字段

class Meta:
    ordering = ['created']

def __str__(self):
    return self.title

“`

步骤 5:数据库迁移

bash
python manage.py makemigrations snippets
python manage.py migrate

步骤 6:创建超级用户 (用于测试)

bash
python manage.py createsuperuser

步骤 7:编写序列化器 (snippets/serializers.py)

(同 2.1 节示例)

步骤 8:创建视图集 (snippets/views.py)

为了简洁和推荐的做法,这里直接使用 ModelViewSetReadOnlyModelViewSet

“`python
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import viewsets
from django.contrib.auth.models import User
from rest_framework import permissions
from .permissions import IsOwnerOrReadOnly # 自定义权限,稍后创建

class SnippetViewSet(viewsets.ModelViewSet):
“””
此视图集自动提供 list, create, retrieve, update, partial_updatedestroy 操作。
“””
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly] # 使用自定义权限

def perform_create(self, serializer):
    """在创建 Snippet 时,自动关联当前登录用户为 owner。"""
    serializer.save(owner=self.request.user)

class UserViewSet(viewsets.ReadOnlyModelViewSet):
“””
此视图集自动提供 listretrieve 操作。
“””
queryset = User.objects.all()
serializer_class = UserSerializer
``
**步骤 8.5:创建自定义权限 (
snippets/permissions.py`)**

“`python
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
“””
自定义权限,只有对象的创建者才能编辑它。
“””
def has_object_permission(self, request, view, obj):
# 允许所有 GET, HEAD 或 OPTIONS 请求。
if request.method in permissions.SAFE_METHODS:
return True

    # 写入权限只赋予给 snippet 的所有者。
    return obj.owner == request.user

“`

步骤 9:配置 URL 路由 (tutorial/urls.py)

“`python
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets.views import SnippetViewSet, UserViewSet

创建一个路由器实例

router = DefaultRouter()

注册我们的视图集到路由器

router.register(r’snippets’, SnippetViewSet, basename=’snippet’) # basename 参数是可选的,但建议显式设置
router.register(r’users’, UserViewSet, basename=’user’)

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(router.urls)), # 将路由器生成的 URL 包含进来
path(‘api-auth/’, include(‘rest_framework.urls’)), # 用于 browsable API 的登录/登出
]
“`

步骤 10:运行与测试

bash
python manage.py runserver

现在,在浏览器中访问 http://127.0.0.1:8000/api/,您将看到一个漂亮的 browsable API 页面,其中列出了您的 snippetsusers 资源。您可以进行 GET 请求,并尝试在登录后(通过 browsable API 顶部的 Login 按钮)创建、更新或删除 Snippet。

4. 提升 API 效率和安全性

构建 API 不仅仅是实现功能,更要注重其性能和安全性。DRF 提供了一系列工具来帮助您实现这些目标。

4.1 认证与权限 (Authentication and Permissions)

  • 认证 (Authentication): 确定是谁发起了请求。DRF 提供了多种认证方式,如 SessionAuthentication (用于 Web 浏览会话)、TokenAuthentication (基于令牌的认证) 和 BasicAuthentication (HTTP Basic 认证)。您可以在 settings.py 中全局配置,或在视图中局部配置。
  • 权限 (Permissions): 确定请求者是否被允许执行某个操作。DRF 提供了 AllowAny (允许所有请求)、IsAuthenticated (只允许认证用户)、IsAdminUser (只允许管理员用户) 等。您可以自定义权限类以实现更复杂的业务逻辑(如上述的 IsOwnerOrReadOnly)。

4.2 限流 (Throttling)

限流用于限制用户在给定时间段内可以向 API 发出的请求数量,以防止滥用和保障服务稳定性。DRF 支持多种限流策略,如 AnonRateThrottle (匿名用户限流) 和 UserRateThrottle (认证用户限流)。

4.3 过滤、搜索与排序 (Filtering, Searching, and Ordering)

当数据集庞大时,用户通常需要根据特定条件筛选、搜索和排序数据。

  • 过滤 (Filtering): 可以使用 django-filter 库与 DRF 结合,提供强大的字段过滤功能。
  • 搜索 (Searching): DRF 内置 SearchFilter,允许通过指定字段进行文本搜索。
  • 排序 (Ordering): DRF 内置 OrderingFilter,允许用户通过 URL 参数指定结果的排序方式。

通过在视图中添加 filter_backends 属性来启用这些功能。

“`python
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend

class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = [‘language’, ‘style’] # 允许通过 language 和 style 字段过滤
search_fields = [‘title’, ‘code’] # 允许通过 title 和 code 字段搜索
ordering_fields = [‘created’, ‘title’] # 允许通过 created 和 title 字段排序
“`

4.4 分页 (Pagination)

分页是处理大型数据集的关键。它限制了单个 API 响应中返回的记录数量,从而减少了服务器负载和网络带宽,提高了响应速度。DRF 提供了 PageNumberPagination (基于页码) 和 LimitOffsetPagination (基于偏移量和限制) 等多种分页器。

“`python

settings.py

REST_FRAMEWORK = {
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10 # 默认每页显示 10 条记录
}

或者在视图中局部设置

class SnippetList(generics.ListCreateAPIView):
# …
pagination_class = CustomPagination # 可以自定义分页器
“`

4.5 性能优化技巧 (Performance Optimization Tips)

  • 数据库查询优化:
    • select_related 用于一对一和多对一关系,在执行查询时“连接”相关对象的数据,减少数据库查询次数。
    • prefetch_related 用于多对多和反向外键关系,通过单独的查询获取相关对象,然后在 Python 中进行“连接”,同样减少查询次数。
  • 缓存机制: 针对不经常变动但频繁访问的数据,使用 Django 的缓存框架(如 Redis 或 Memcached)可以显著提高响应速度。
  • 惰性加载 (Lazy Loading): 确保只在真正需要时才加载数据,避免不必要的数据库查询。
  • 限制序列化器字段: 在某些场景下,客户端可能只需要部分字段。通过在序列化器中动态排除或包含字段,可以减少数据传输量。

5. 高级特性

DRF 的强大之处在于其可扩展性,您可以根据项目需求定制各种组件。

  • 自定义字段和序列化器方法: 当内置字段无法满足需求时,可以创建自定义序列化器字段,或在序列化器中定义 create()update() 以及自定义方法来处理复杂的数据逻辑。
  • 解析器 (Parsers) 和渲染器 (Renderers): DRF 默认支持 JSON 数据的解析和渲染。您可以通过自定义解析器来处理其他请求体格式(如 XML),通过自定义渲染器来生成其他响应格式。
  • 版本控制 (Versioning): 随着 API 的演进,保持向后兼容性至关重要。DRF 提供了 URL 版本控制、Header 版本控制、Query 参数版本控制等多种策略,帮助您管理 API 的不同版本。
  • API 文档: 良好的 API 文档是提高开发效率和可用性的关键。结合 drf-yasgrest_framework_swagger 等第三方库,可以自动为您的 DRF API 生成交互式 Swagger/OpenAPI 文档。

6. 总结

Django REST Framework 是一个功能丰富、设计优雅的 Python 库,它极大地简化了 RESTful API 的开发过程。从基础的序列化和视图到高级的认证、权限、性能优化和文档生成,DRF 提供了一整套解决方案。

通过本文的介绍和实践,您应该已经对如何使用 DRF 快速构建高效的 RESTful API 有了全面的了解。DRF 强大的抽象层和灵活的定制能力,将使您能够专注于业务逻辑的实现,而无需过多地关注底层 API 细节。现在,是时候将这些知识付诸实践,构建您自己的强大 API 了!


This article aims to provide a comprehensive overview of learning DRF, from basic concepts to advanced features and efficiency tips.
The article covers:
1. Introduction to DRF and its advantages.
2. Core concepts: Serializers, Views (APIView, Generic Views, ViewSets), and Routers.
3. A quick start guide to build a basic Snippet API, including environment setup, model definition, serializer creation, viewset implementation, and URL configuration.
4. Enhancing API efficiency and security with Authentication, Permissions, Throttling, Filtering, Searching, Ordering, and Pagination, along with performance optimization tips.
5. Advanced features like custom fields, parsers/renderers, versioning, and API documentation.
6. A concluding summary.

I tried to incorporate the practical code examples and explanations that are common in DRF tutorials, based on the search results.
The article is written in Chinese as requested.
The task is complete.文章已撰写完成,详细描述了学习 Django REST Framework 以快速构建高效 RESTful API 的过程,涵盖了核心概念、快速入门、效率与安全提升以及高级特性。

滚动至顶部