一文读懂 Django REST Framework (DRF) – wiki基地


一文读懂 Django REST Framework (DRF)

在现代Web开发中,构建强大的、可供不同客户端(如Web浏览器、移动应用、第三方服务)消费的API已成为核心需求。Django以其”快速开发,避免重复造轮子”的理念闻名,而Django REST Framework (DRF)正是Django生态系统中最受欢迎、功能最强大的工具,用于构建RESTful API。

本文将带你深入了解DRF,从其基本概念到核心组件,再到实际应用,力求让你“一文读懂”DRF的精髓。

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

在深入DRF之前,我们先简单回顾一下RESTful API的概念。REST(Representational State Transfer)是一种架构风格,用于设计网络应用程序接口。遵循RESTful原则的API通常具有以下特点:

  • 无状态 (Stateless): 服务器不存储客户端的状态信息。
  • 客户端-服务器分离 (Client-Server): 客户端和服务器的职责分离。
  • 统一接口 (Uniform Interface): 使用标准的HTTP方法(GET, POST, PUT, PATCH, DELETE)操作资源。
  • 资源 (Resources): 数据被抽象为资源,每个资源都有一个URI(统一资源标识符)。
  • 表现形式 (Representational): 资源通过某种表现形式(如JSON, XML)在客户端和服务器之间传输。
  • 分层系统 (Layered System): 客户端无法感知它是否直接连接到最终服务器,或者中间是否有代理、网关等。

为什么选择 DRF?

虽然你可以使用Django自身的功能来构建返回JSON或XML的视图,但这会非常繁琐。你需要手动处理:

  • 解析请求体(JSON, XML等)。
  • 验证输入数据。
  • 将Python对象序列化成可传输的格式(JSON, XML等)。
  • 处理认证和权限。
  • 实现分页、过滤、搜索等功能。
  • 生成API文档。

DRF正是为了解决这些痛点而生。它提供了一套强大而灵活的工具集,极大地简化了构建Web API的过程:

  • 序列化器 (Serializers): 轻松地将Django模型或其他数据源转换为API响应所需的格式,并处理反序列化和数据验证。
  • 视图 (Views): 提供基于类的视图(Class-Based Views, CBVs)和通用视图(Generic Views),极大地减少了编写视图逻辑所需的代码。
  • 认证与权限 (Authentication & Permissions): 内置多种认证和权限方案,轻松控制谁可以访问你的API以及他们能做什么。
  • 分页、过滤与搜索 (Pagination, Filtering & Searching): 提供简单的配置来实现这些常见的API功能。
  • 可浏览的API (Browsable API): DRF自带一个美观的、可用于测试和调试API的Web界面。
  • 灵活的渲染器与解析器 (Renderers & Parsers): 支持多种数据格式(JSON, XML, HTML等),并可轻松扩展。
  • 强大的文档生成 (Documentation): 易于集成API文档生成工具。

总而言之,DRF是构建高效、可维护、功能丰富的Django API的首选框架。

2. 安装与基本配置

开始使用DRF非常简单。

安装:

bash
pip install djangorestframework

配置:

'rest_framework' 添加到你的Django项目的 settings.py 文件中的 INSTALLED_APPS 列表中:

“`python

settings.py

INSTALLED_APPS = [
# … 其他应用
‘rest_framework’,
# 如果需要Token认证,还需要这个
‘rest_framework.authtoken’,
]
“`

这样,DRF就集成到了你的Django项目中。

3. 核心概念详解

理解DRF的核心概念是掌握它的关键。它们包括:

3.1 Serializers (序列化器)

序列化器是DRF中最核心也是最重要的组件之一。它的主要职责有两个:

  1. 序列化 (Serialization): 将复杂的Python数据类型(如Django模型实例、查询集)转换为可传输的格式(如JSON、XML)。
  2. 反序列化 (Deserialization): 将接收到的可传输格式数据(如JSON请求体)转换回Python数据类型,并对数据进行验证。

这就像API的输入输出转换器和数据校验器。

基本使用:

我们通常使用 rest_framework.serializers.Serializerrest_framework.serializers.ModelSerializer

  • Serializer: 用于处理非模型数据,或者需要完全自定义字段和验证逻辑时。
  • ModelSerializer: 用于直接与Django模型关联。它可以自动生成字段和基本验证,大大简化代码。这是最常用的方式。

示例:使用 ModelSerializer

假设我们有一个简单的模型:

“`python

models.py

from django.db import models

class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
in_stock = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)

def __str__(self):
    return self.name

“`

创建一个对应的序列化器:

“`python

serializers.py

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [‘id’, ‘name’, ‘price’, ‘in_stock’, ‘created_at’]
# 或者使用 exclude = [‘some_field’] 排除特定字段
# 或者使用 fields = ‘all‘ 包含所有字段 (不推荐,不够明确)
# read_only_fields = [‘created_at’] # 这些字段只用于输出,不用于输入验证
“`

序列化数据:

“`python

在 Django shell 或视图中

from .models import Product
from .serializers import ProductSerializer

序列化单个对象

product = Product.objects.first()
serializer = ProductSerializer(product)
print(serializer.data) # 输出一个字典,可以转换为 JSON

序列化查询集 (多个对象)

queryset = Product.objects.all()
serializer = ProductSerializer(queryset, many=True) # many=True 是关键
print(serializer.data) # 输出一个字典列表,可以转换为 JSON 数组
“`

反序列化与验证:

当接收到客户端发送的数据(通常是PUT/POST/PATCH请求的请求体)时,我们使用序列化器进行反序列化和验证。

“`python

假设 request.data 包含了客户端发送的数据,比如 {“name”: “New Product”, “price”: 199.99, “in_stock”: true}

from .serializers import ProductSerializer

serializer = ProductSerializer(data=request.data) # 将输入数据传给 data 参数

if serializer.is_valid(): # 执行验证
# 数据有效
product_instance = serializer.save() # 调用 serializer.save() 创建或更新对象
# product_instance 就是创建或更新后的 Product 模型实例
print(“数据有效,保存成功!”)
print(product_instance)
else:
# 数据无效
print(serializer.errors) # 包含验证失败的错误信息字典
“`

serializer.save() 方法会自动调用 create()update() 方法:

  • 如果序列化器是用 data 参数初始化的(用于创建),它会调用 serializer.create(validated_data)
  • 如果序列化器是用一个模型实例和一个 data 参数初始化的(用于更新),它会调用 serializer.update(instance, validated_data)

你可以在序列化器中重写 create()update() 方法来添加自定义保存逻辑。

自定义字段和验证:

可以在序列化器中显式定义字段,这允许你定制字段的行为、添加只读字段、写字段(Write-only fields)、计算字段等。

“`python

serializers.py

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
# 添加一个只读的计算字段
is_expensive = serializers.SerializerMethodField()
# 定义一个写字段,只用于输入,不用于输出
category_name = serializers.CharField(write_only=True)

class Meta:
    model = Product
    fields = ['id', 'name', 'price', 'in_stock', 'created_at', 'is_expensive', 'category_name']
    read_only_fields = ['created_at'] # 也可以在这里设置只读字段

def get_is_expensive(self, obj):
    # obj 是 Product 模型实例
    return obj.price > 100.00

# 对象级别的验证
def validate(self, data):
    # 假设我们不允许价格为负数
    if data.get('price') < 0:
        raise serializers.ValidationError({"price": "价格不能为负数。"})
    return data

# 字段级别的验证
def validate_name(self, value):
    # 假设产品名称不能包含“测试”二字
    if "测试" in value:
        raise serializers.ValidationError("产品名称不能包含‘测试’。")
    return value

# 重写 create 方法(示例:假设 category_name 用于查找或创建 Category 关联)
def create(self, validated_data):
    category_name = validated_data.pop('category_name', None)
    # 这里可以根据 category_name 处理 Category 关联逻辑
    product = Product.objects.create(**validated_data)
    return product

“`

序列化器是DRF数据处理的核心,掌握它至关重要。

3.2 Views (视图)

DRF的视图负责处理请求并返回响应。它们与Django视图类似,但提供了更多API特有的功能,如自动处理认证、权限、内容协商等。

DRF提供了几种不同层次的视图抽象:

  1. APIView: DRF最基础的视图类,继承自Django的 View。它提供了DRF的核心功能,如 .get(), .post() 等方法,并会自动处理DRF的 RequestResponse 对象,应用认证、权限、限流等策略。当你需要完全自定义视图逻辑时使用它。
  2. Generic APIViews (通用API视图): DRF提供了一系列预定义的通用视图类,用于处理常见的模型操作,如列表、详情、创建、更新、删除。它们通过结合 Mixins (混入类)GenericAPIView 实现。这极大地减少了代码量。
    • ListAPIView: 只读列表。
    • RetrieveAPIView: 只读详情。
    • CreateAPIView: 只写创建。
    • UpdateAPIView: 只写更新。
    • DestroyAPIView: 只写删除。
    • ListCreateAPIView: 列表和创建。
    • RetrieveUpdateDestroyAPIView: 详情、更新和删除。
    • RetrieveUpdateAPIView: 详情和更新。
    • RetrieveDestroyAPIView: 详情和删除。
      使用它们时,你通常只需设置 querysetserializer_class 属性。
  3. ViewSets (视图集): DRF的最高层次抽象。它将一组相关的视图逻辑(如列表、详情、创建、更新、删除)组合到一个类中,而不是像常规视图那样分散到多个URL。ViewSets通常与 Routers 配合使用,可以自动生成URL配置。
    • ViewSet: 基础视图集,需要自己实现 .list(), .retrieve(), .create() 等方法。
    • GenericViewSet: 结合了 GenericAPIView 的功能,可以与Mixins配合使用,但没有默认提供 list, retrieve 等方法,需要手动添加Mixins。
    • ModelViewSet: 继承自 GenericViewSet 并包含了所有标准的 Mixins (ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin, DestroyModelMixin)。它是处理Django模型CRUD操作最快捷的方式。你只需设置 querysetserializer_class

示例:使用不同类型的视图

APIView 示例:

“`python

views.py

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Product
from .serializers import ProductSerializer

class ProductListAPIView(APIView):
“””
List all products or create a new product.
“””
def get(self, request, format=None):
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)

def post(self, request, format=None):
    serializer = ProductSerializer(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)

URL 配置 (urls.py)

from django.urls import path
from .views import ProductListAPIView

urlpatterns = [
path(‘products/’, ProductListAPIView.as_view(), name=’product-list’),
]
“`

Generic APIView 示例 (ListCreateAPIView):

“`python

views.py

from rest_framework import generics
from .models import Product
from .serializers import ProductSerializer

class ProductListCreateAPIView(generics.ListCreateAPIView):
“””
List all products or create a new product (using Generic View).
“””
queryset = Product.objects.all()
serializer_class = ProductSerializer

URL 配置 (urls.py)

from django.urls import path
from .views import ProductListCreateAPIView

urlpatterns = [
path(‘products/’, ProductListCreateAPIView.as_view(), name=’product-list-create’),
]
“`
可以看到使用 Generic Views 代码量大大减少。

ModelViewSet 示例:

“`python

views.py

from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
“””
A simple ViewSet for viewing and editing products.
Provides: list, retrieve, create, update, partial_update, destroy actions.
“””
queryset = Product.objects.all()
serializer_class = ProductSerializer

URL 配置通常使用 Routers (详见下文)

“`

选择哪种视图取决于你的需求。对于简单的CRUD操作,ModelViewSet 是最快的;对于组合操作或需要自定义逻辑较多时,Generic APIViews 方便;当需要完全控制请求/响应流程时,使用 APIView

3.3 URLs and Routers (URLs 和 路由)

将视图映射到URL是构建API的下一步。对于基于 APIView 或 Generic Views 的视图,你使用标准的Django urls.py 配置:

“`python

urls.py

from django.urls import path

from .views import ProductListAPIView, ProductDetailAPIView # 假设你写了详情视图

urlpatterns = [
path(‘products/’, ProductListAPIView.as_view(), name=’product-list’),
# path(‘products//’, ProductDetailAPIView.as_view(), name=’product-detail’),
]
“`

对于 ViewSets,DRF提供了一个强大的工具 Routers (路由),它可以根据 ViewSet 自动生成标准的URL配置(列表、详情等)。

示例:使用 DefaultRouter

“`python

urls.py

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet # 假设你定义了 ProductViewSet

创建一个路由器实例

router = DefaultRouter()

注册 ViewSet

第一个参数是 URL 前缀,第二个参数是 ViewSet 类,第三个参数是可选的 base_name (用于生成 URL 名称)

router.register(r’products’, ProductViewSet, basename=’product’)

urlpatterns 现在包含了由路由器自动生成的 URL

urlpatterns = [
path(”, include(router.urls)), # 包含路由器生成的 URL
# 你也可以在这里添加其他的非 ViewSet 的 URL
# path(‘some-custom-path/’, some_custom_view.as_view(), name=’custom-view’),
]
“`

使用 DefaultRouter 注册 ProductViewSet 后,它会自动生成如下URL模式(假设URL前缀是 /):

  • /products/ (GET: list, POST: create)
  • /products/{pk}/ (GET: retrieve, PUT: update, PATCH: partial_update, DELETE: destroy)

DefaultRouter 还提供了可浏览API的入口点和格式后缀模式。如果你不需要这些,可以使用 SimpleRouter

Router 是 ViewSets 的完美搭档,它们共同极大地提高了API开发效率。

3.4 Requests and Responses (请求和响应)

DRF 引入了增强型的 RequestResponse 对象:

  • Request: DRF的 Request 对象继承自Django的 HttpRequest,但提供了更灵活的解析功能。
    • request.data: 包含了解析后的请求体内容,不论是POST、PUT、PATCH请求,也不论内容是JSON、XML还是表单数据,DRF都会根据请求头的 Content-Type 使用合适的解析器进行解析。
    • request.query_params: Django原生的 request.GET,用于获取URL中的查询参数。
    • request.parser_classes: 控制请求使用哪些解析器。
  • Response: DRF的 Response 对象继承自Django的 HttpResponse,但它接受未渲染的Python数据(如字典、列表)作为参数,并使用内容协商机制根据客户端请求头 (Accept 头部) 和配置的渲染器自动渲染为合适的格式(默认为JSON)。你还可以方便地设置HTTP状态码。

“`python

示例:在 APIView 中使用 Request 和 Response

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class MyView(APIView):
def post(self, request, format=None):
# 获取解析后的请求体数据
data = request.data
print(data)

    # 处理数据...

    # 返回响应,DRF会自动将其渲染为 JSON (或其他格式)
    return Response({"message": "Data received", "your_data": data}, status=status.HTTP_201_CREATED)

“`

3.5 Authentication (认证)

认证是确定谁发出了请求的过程。DRF提供了多种认证方案:

  • SessionAuthentication: 使用Django的标准session/cookie认证。适合与基于session的Web界面结合使用。
  • BasicAuthentication: 使用HTTP Basic认证,将用户名和密码 Base64 编码后放在 Authorization 头部。不安全,通常只用于测试或内部服务。
  • TokenAuthentication: 基于Token的认证。用户登录后获取一个Token,后续请求在 Authorization 头部携带此Token (Token <the_token>) 进行认证。适合移动应用或第三方服务调用。需要将 rest_framework.authtoken 加入 INSTALLED_APPS 并运行迁移。
  • RemoteUserAuthentication: 使用Web服务器提供的认证信息。
  • OAuth1/OAuth2 等第三方认证库也可以与DRF集成。

配置:

可以在 settings.py 中全局配置默认认证类:

“`python

settings.py

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’,
‘rest_framework.authentication.SessionAuthentication’, # 可以同时配置多种
],
# … 其他配置
}
“`

也可以在单个视图或 ViewSet 中配置:

“`python

views.py

from rest_framework.views import APIView
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated # 通常与权限一起使用

class SecuredView(APIView):
authentication_classes = [TokenAuthentication] # 仅使用Token认证
permission_classes = [IsAuthenticated] # 要求用户已认证

def get(self, request, format=None):
    # request.user 将是被认证的用户实例 (如果认证成功)
    return Response({"message": f"Hello, {request.user.username}!"})

“`

当认证成功后,request.user 会被设置为对应的用户实例,request.auth 会被设置为认证凭证(如Token实例)。

3.6 Permissions (权限)

权限是确定已认证用户是否有权执行某个操作的过程。认证只告诉你“是谁”,权限才决定“能做什么”。

DRF提供了多种权限类:

  • AllowAny: 允许任何用户(包括未认证用户)访问。这是默认设置。
  • IsAuthenticated: 只允许已认证用户访问。
  • IsAdminUser: 只允许Django管理员用户访问。
  • IsAuthenticatedOrReadOnly: 允许已认证用户进行写操作(POST, PUT, PATCH, DELETE),未认证用户只能进行读操作(GET, HEAD, OPTIONS)。
  • DjangoModelPermissions: 基于Django的 django.contrib.auth 模型权限系统。
  • DjangoObjectPermissions: 基于Django的对象级别权限系统(如 django-guardian)。

配置:

可以在 settings.py 中全局配置默认权限类:

“`python

settings.py

REST_FRAMEWORK = {
# … 其他配置
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’, # 默认要求所有API都需要认证
]
}
“`

也可以在单个视图或 ViewSet 中配置:

“`python

views.py

from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# 配置视图集的权限
permission_classes = [IsAuthenticatedOrReadOnly] # 列表和详情允许任何人,创建、更新、删除只允许认证用户

# 对于特定的 action 可以覆盖权限
def get_permissions(self):
    if self.action == 'create':
        # 只有管理员才能创建产品
        return [IsAdminUser()]
    return super().get_permissions() # 其他操作使用 IsAuthenticatedOrReadOnly

“`

自定义权限:

可以继承 rest_framework.permissions.BasePermission 类并实现 has_permission(self, request, view) (对象级别,检查用户是否有权限访问 这个视图这类对象) 和 has_object_permission(self, request, view, obj) (对象级别,检查用户是否有权限对 这个特定对象 执行操作)。

“`python

permissions.py

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
“””
Custom permission to only allow owners of an object to edit it.
“””

def has_object_permission(self, request, view, obj):
    # Read permissions are allowed to any request,
    # so we'll always allow GET, HEAD or OPTIONS requests.
    if request.method in permissions.SAFE_METHODS:
        return True

    # Write permissions are only allowed to the owner of the snippet.
    # Assuming the model instance has an 'owner' attribute.
    return obj.owner == request.user

在 views.py 中使用

class SomeModelViewSet(viewsets.ModelViewSet):

queryset = SomeModel.objects.all()

serializer_class = SomeModelSerializer

permission_classes = [IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly] # 注意顺序,通常先检查通用权限,再检查对象权限

“`

3.7 Pagination (分页)

当数据集很大时,一次性返回所有数据会导致性能问题和网络延迟。分页可以将结果集分割成小块返回。

DRF内置了三种分页器:

  • PageNumberPagination: 基于页码的分页。客户端通过查询参数 ?page=N?page_size=M 请求特定页码和每页数量。
  • LimitOffsetPagination: 基于偏移量和数量的分页。客户端通过 ?limit=M?offset=N 请求。类似于SQL的 LIMITOFFSET
  • CursorPagination: 基于游标的分页。更适合处理大型、不断变化的数据集,因为它基于数据中的某个固定点(游标)获取下一批数据,避免了传统分页可能出现的重复或跳过数据问题。它要求数据集有一个固定的、唯一的排序字段。

配置:

可以在 settings.py 中全局配置默认分页样式:

“`python

settings.py

REST_FRAMEWORK = {
# … 其他配置
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10, # 默认每页数量
}
“`

也可以在单个视图或 ViewSet 中配置:

“`python

views.py

from rest_framework import viewsets
from rest_framework.pagination import LimitOffsetPagination

… (其他导入)

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = LimitOffsetPagination # 只对此视图集应用 LimitOffsetPagination
# 对于 LimitOffsetPagination,可以通过 settings.py 或 view/viewset 设置 limit_query_param, offset_query_param 等
# limit_query_param = ‘count’ # 示例:客户端用 ?count=…
# offset_query_param = ‘start’ # 示例:客户端用 ?start=…
“`

3.8 Filtering and Searching (过滤和搜索)

允许客户端通过URL查询参数过滤或搜索结果集是API的常见需求。DRF通过过滤器后端(Filter Backends)实现这些功能。

常用的过滤器后端:

  • rest_framework.filters.DjangoFilterBackend: 最常用的过滤器后端,通常与第三方库 django-filter 结合使用,实现强大的字段过滤。
  • rest_framework.filters.SearchFilter: 实现基于字段的模糊搜索。
  • rest_framework.filters.OrderingFilter: 实现结果集的排序。

安装 django-filter (如果使用 DjangoFilterBackend):

bash
pip install django-filter

添加到 settings.py

“`python

settings.py

INSTALLED_APPS = [
# …
‘django_filters’,
# …
]

如果全局配置 DjangoFilterBackend

REST_FRAMEWORK = {
# …
‘DEFAULT_FILTER_BACKENDS’: [‘django_filters.rest_framework.DjangoFilterBackend’],
}
“`

使用示例:

“`python

views.py

from rest_framework import viewsets
from rest_framework import filters
from django_filters.rest_framework import DjangoFilterBackend # 导入 DjangoFilterBackend
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# 配置过滤器后端
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
# 配置 DjangoFilterBackend 允许过滤的字段
filterset_fields = [‘category’, ‘in_stock’] # 假设 Product 模型有 category 外键或字段
# 配置 SearchFilter 允许搜索的字段 (使用 __ 操作符指定搜索方式)
search_fields = [‘name’, ‘description’] # 搜索 name 和 description 字段 (默认为 __icontains)
# 配置 OrderingFilter 允许排序的字段
ordering_fields = [‘price’, ‘created_at’] # 允许按 price 和 created_at 排序
# 默认排序字段
ordering = [‘-created_at’] # 默认按创建时间降序排列
“`

有了这些配置,客户端就可以这样请求数据:

  • /products/?category=electronics&in_stock=true (过滤)
  • /products/?search=laptop (搜索)
  • /products/?ordering=price (按价格升序排序)
  • /products/?ordering=-price (按价格降序排序)
  • /products/?category=electronics&search=phone&ordering=-price (组合使用)

3.9 Versioning (版本控制)

API通常会随着时间演进,为了不破坏现有客户端,需要进行版本控制。DRF提供了多种版本控制方案:

  • URLPathVersioning: 将版本号包含在URL路径中 (e.g., /v1/products/)。
  • NamespaceVersioning: 基于URL命名空间的版本控制。
  • QueryParameterVersioning: 将版本号作为查询参数 (e.g., /products/?version=v1)。
  • HostNameVersioning: 将版本号作为主机名的一部分 (e.g., v1.api.example.com/products/)。
  • AcceptHeaderVersioning: 将版本号包含在 Accept 头部中 (e.g., Accept: application/json; version=v1)。

配置:

“`python

settings.py

REST_FRAMEWORK = {
# …
‘DEFAULT_VERSIONING_CLASS’: ‘rest_framework.versioning.URLPathVersioning’,
‘DEFAULT_VERSION’: ‘v1’, # 默认版本
‘ALLOWED_VERSIONS’: [‘v1’, ‘v2’], # 允许的版本
‘VERSION_PARAM’: ‘version’, # 在 URL 中用于表示版本的参数名
}

urls.py (使用 URLPathVersioning 示例)

from django.urls import path, include, re_path
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet # v1
from .views_v2 import ProductViewSet as ProductViewSetV2 # v2

router_v1 = DefaultRouter()
router_v1.register(r’products’, ProductViewSet, basename=’product-v1′)

router_v2 = DefaultRouter()
router_v2.register(r’products’, ProductViewSetV2, basename=’product-v2′)

urlpatterns = [
re_path(r’^v(?P[0-9.]+)/’, include(router_v1.urls)), # URL 路径包含版本号
# 或者为 v2 单独定义 URL
# re_path(r’^v(?P[0-9.]+)/v2/’, include(router_v2.urls)), # 如果 v2 有不同 URL 结构
# 更简单的办法通常是在 viewset/serializer 里根据 request.version 判断版本
# 或者为不同版本创建完全独立的 urls.py 文件
]
“`

选择合适的版本控制策略取决于你的项目需求和偏好。

3.10 Throttling (限流)

限流用于控制客户端在一定时间内可以向API发出的请求数量,以防止滥用和过载。

DRF提供了几种限流策略:

  • AnonRateThrottle: 限制未经认证用户的请求速率。
  • UserRateThrottle: 限制已认证用户的请求速率。
  • ScopedRateThrottle: 限制特定作用域(如某个API endpoint)的请求速率。

配置:

可以在 settings.py 中全局配置:

“`python

settings.py

REST_FRAMEWORK = {
# …
‘DEFAULT_THROTTLE_CLASSES’: [
‘rest_framework.throttling.AnonRateThrottle’,
‘rest_framework.throttling.UserRateThrottle’
],
‘DEFAULT_THROTTLE_RATES’: {
‘anon’: ‘100/day’, # 匿名用户每天最多100次请求
‘user’: ‘1000/day’, # 认证用户每天最多1000次请求
‘ burst’: ’60/min’, # 示例:自定义作用域限流
‘sustained’: ‘1000/day’, # 示例:自定义作用域限流
}
}
“`

也可以在视图或 ViewSet 中配置:

“`python

views.py

from rest_framework.views import APIView
from rest_framework.throttling import ScopedRateThrottle

class ProductListView(APIView):
# … (其他属性)
throttle_classes = [ScopedRateThrottle]
throttle_scope = ‘products_list’ # 定义作用域名称

settings.py 中配置这个作用域的限流速率

REST_FRAMEWORK = {

‘DEFAULT_THROTTLE_RATES’: {

‘products_list’: ’60/minute’, # 每分钟最多60次请求

}

}

“`

3.11 Renderers and Parsers (渲染器和解析器)

  • Renderers (渲染器): 控制API响应如何被渲染成特定媒体类型的内容(如JSON、HTML)。DRF内置了 JSONRenderer, BrowsableAPIRenderer, StaticHTMLRenderer 等。
  • Parsers (解析器): 控制DRF如何解析请求体的内容,将其转换为 request.data。DRF内置了 JSONParser, FormParser, MultiPartParser 等。

DRF使用 内容协商 (Content Negotiation) 机制,根据客户端请求头 Accept(对于渲染器)或 Content-Type(对于解析器)来选择合适的类进行处理。

配置:

可以在 settings.py 中全局配置默认的渲染器和解析器:

“`python

settings.py

REST_FRAMEWORK = {
# …
‘DEFAULT_RENDERER_CLASSES’: [
‘rest_framework.renderers.JSONRenderer’,
‘rest_framework.renderers.BrowsableAPIRenderer’, # 通常在开发环境中开启
],
‘DEFAULT_PARSER_CLASSES’: [
‘rest_framework.parsers.JSONParser’,
‘rest_framework.parsers.FormParser’, # 处理表单数据
‘rest_framework.parsers.MultiPartParser’ # 处理文件上传
]
}
“`

也可以在视图或 ViewSet 中配置:

“`python

views.py

from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

class MyJsonView(APIView):
renderer_classes = [JSONRenderer] # 只渲染为 JSON
parser_classes = [JSONParser] # 只解析 JSON 请求体

# ...

“`

BrowsableAPIRenderer 是DRF非常酷炫的功能,它在浏览器访问API时提供了一个交互式的HTML界面,方便测试和调试。在生产环境中,通常会移除它,只保留 JSONRenderer 等。

4. 整合示例:构建一个简单的产品 API

我们将前面介绍的核心概念整合起来,构建一个简单的产品API。

1. 创建应用和模型:

bash
python manage.py startapp products_api

products_api/models.py 中定义 Product 模型 (如上文所示)。
添加到 INSTALLED_APPS 并运行迁移。

2. 创建 Serializer:

products_api/serializers.py 中定义 ProductSerializer (如上文所示)。

3. 创建 ViewSet:

products_api/views.py 中定义 ProductViewSet (使用 ModelViewSet,如上文所示)。

“`python

products_api/views.py

from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
# 添加一些常用的功能
filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
filterset_fields = [‘in_stock’]
search_fields = [‘name’]
ordering_fields = [‘price’, ‘created_at’]
# pagination_class = PageNumberPagination # 如果需要分页,在此或 settings 中配置
# permission_classes = [IsAuthenticatedOrReadOnly] # 如果需要权限控制
``
*(注意:这里假设已经安装并配置了
django-filterrest_framework.filters`)*

4. 配置 URL 使用 Router:

在项目主 urls.py 中配置路由:

“`python

project/urls.py

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from products_api.views import ProductViewSet # 导入 ViewSet

router = DefaultRouter()
router.register(r’products’, ProductViewSet) # 注册产品 ViewSet

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(router.urls)), # 将 DRF 路由包含在 /api/ 路径下
# path(‘api-auth/’, include(‘rest_framework.urls’)), # 可选:为可浏览API添加登录/注销功能
]
“`

5. 配置 settings.py (可选):

根据需要配置全局认证、权限、分页、限流等。

“`python

settings.py

REST_FRAMEWORK = {
# Use Django’s standard django.contrib.auth permissions,
# or allow read-only access for unauthenticated users.
# ‘DEFAULT_PERMISSION_CLASSES’: [
# ‘rest_framework.permissions.IsAuthenticatedOrReadOnly’
# ],
# ‘DEFAULT_AUTHENTICATION_CLASSES’: [
# ‘rest_framework.authentication.SessionAuthentication’,
# ‘rest_framework.authentication.TokenAuthentication’,
# ],
# ‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
# ‘PAGE_SIZE’: 10,
# ‘DEFAULT_FILTER_BACKENDS’: [
# ‘django_filters.rest_framework.DjangoFilterBackend’,
# ‘rest_framework.filters.SearchFilter’,
# ‘rest_framework.filters.OrderingFilter’,
# ],
# ‘DEFAULT_THROTTLE_CLASSES’: [
# ‘rest_framework.throttling.AnonRateThrottle’,
# ‘rest_framework.throttling.UserRateThrottle’
# ],
# ‘DEFAULT_THROTTLE_RATES’: {
# ‘anon’: ‘100/day’,
# ‘user’: ‘1000/day’
# }
}
“`

6. 运行服务器并测试:

bash
python manage.py runserver

现在你可以通过浏览器访问 http://127.0.0.1:8000/api/products/,如果开启了 BrowsableAPIRenderer,你将看到一个漂亮的可浏览API界面,可以进行列表、创建、查看、更新、删除等操作。

你也可以使用 curl 或 Postman 等工具测试:

  • GET http://127.0.0.1:8000/api/products/ (获取产品列表)
  • POST http://127.0.0.1:8000/api/products/ -H "Content-Type: application/json" -d '{"name": "Test Product", "price": 50.00}' (创建产品)
  • GET http://127.0.0.1:8000/api/products/1/ (获取ID为1的产品详情)
  • PUT http://127.0.0.1:8000/api/products/1/ -H "Content-Type: application/json" -d '{"name": "Updated Product", "price": 55.00}' (更新产品)
  • DELETE http://127.0.0.1:8000/api/products/1/ (删除产品)
  • GET http://127.0.0.1:8000/api/products/?in_stock=true&search=Test&ordering=-price (过滤、搜索、排序)

这个简单的示例展示了DRF如何使用 ModelViewSetRouter 快速构建一个功能齐全的API。

5. 进一步学习方向

本文涵盖了DRF的核心组件。要更深入地掌握它,你可以探索以下主题:

  • 自定义 Serializer 字段和验证: 处理更复杂的数据结构和业务逻辑。
  • 关系型 Serializers: 处理模型间的关联关系(ForeignKey, ManyToManyField等)。
  • 自定义 Views 和 ViewSets: 实现非标准的API逻辑。
  • 自定义认证和权限类: 实现更细粒度的访问控制。
  • 自定义 Renderer 和 Parser: 支持其他数据格式。
  • API 文档: 使用 drf-yasgcoreapi 等工具生成 Swagger/OpenAPI 文档。
  • 测试 API: 使用DRF提供的 APIClient 进行单元和集成测试。
  • 信号 (Signals): DRF提供了一些信号,可以在请求处理的不同阶段执行自定义逻辑。
  • 性能优化: 序列化器优化、查询集优化等。
  • 与其他库集成: OAuth, GraphQL 等。

DRF的官方文档非常详尽,是学习和查阅资料的最佳来源。

6. 总结

Django REST Framework 是构建Django API的基石。它提供了一套设计精良、功能强大的工具集,包括序列化器、视图、路由、认证、权限、分页、过滤、搜索等,极大地简化了API的开发过程。

通过理解并灵活运用DRF的核心概念,你可以快速高效地构建出符合RESTful原则、易于维护、性能优越的Web API,为你的Web应用提供强大的数据接口。

从简单的 ModelSerializerModelViewSet 入手,逐步学习和掌握DRF的各项功能,你将能够应对各种复杂的API开发需求。DRF不仅仅是一个框架,更是一种利用Django的强大能力构建现代API的强大范式。

希望本文能为你理解和入门DRF提供坚实的基础。祝你在使用DRF的道路上越走越远!


发表评论

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

滚动至顶部