Django REST Framework 核心概念与实战 – wiki词典

Django REST Framework 核心概念与实战详解

Django REST Framework (DRF) 是一个强大而灵活的工具包,用于在 Django 的基础上构建 Web API。它极大地简化了 API 的开发过程,提供了认证、授权、序列化、视图集、路由等一系列开箱即用的功能,让开发者能够专注于业务逻辑而不是底层协议的实现。

本文将深入探讨 DRF 的核心概念,并通过一个实际的例子来演示如何使用 DRF 构建一个简单的 RESTful API。

一、 DRF 核心概念

1. Serializers(序列化器)

序列化器是 DRF 最核心的概念之一,它的主要作用有:
* 序列化 (Serialization):将复杂的 Django 模型实例(或查询集)转换为原生 Python 数据类型(如字典、列表),进而可以轻松地渲染成 JSON、XML 等格式的响应。
* 反序列化 (Deserialization):将接收到的原生 Python 数据类型(通常来自请求体)转换为 Django 模型实例,并进行数据验证。

DRF 提供了多种序列化器:

  • Serializer: 最基础的序列化器,用于完全自定义字段。
  • ModelSerializer: 最常用的序列化器,它能自动根据 Django 模型生成对应的字段,大大简化了开发。它还支持验证和创建/更新模型实例。
  • ListSerializer: 用于处理模型实例列表的序列化。

示例 (ModelSerializer):

“`python

models.py

from django.db import models

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

def __str__(self):
    return self.name

serializers.py

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = [‘id’, ‘name’, ‘description’, ‘price’, ‘in_stock’]
# 或者 fields = ‘all
# read_only_fields = [‘id’] # 设置只读字段
“`

2. Requests & Responses(请求与响应)

DRF 扩展了 Django 的 HttpRequestHttpResponse 对象,提供了更强大的功能:

  • Request 对象: DRF 的 Request 对象继承自 Django 的 HttpRequest,但提供了更灵活的请求解析。它能自动处理不同内容类型(如 JSON、XML)的请求体,并通过 request.data 属性提供解析后的数据。
  • Response 对象: DRF 的 Response 对象继承自 Django 的 HttpResponse,允许你将任何可序列化的数据传递给它,并指定内容的渲染器(如 JSONRenderer、BrowsableAPIRenderer)。DRF 会自动将数据渲染成适当的格式。

“`python
from rest_framework.response import Response
from rest_framework.decorators import api_view

@api_view([‘GET’])
def hello_world(request):
return Response({“message”: “Hello, world!”})
“`

3. ViewSets(视图集)与 Routers(路由器)

DRF 的 ViewSet 是基于 APIView 构建的,但它将一组相关的视图逻辑(如 list, retrieve, create, update, destroy)组合在一个类中。ViewSet 不提供直接的 HTTP 方法处理,而是通过 Router 映射到具体的 HTTP 方法。

ViewSet 的优势:
* 代码组织: 将相关操作封装在一个类中,提高代码可读性和可维护性。
* DRY (Don’t Repeat Yourself): 避免重复编写 list, detail, create 等视图逻辑。
* 自动化 URL 配置: 配合 Router 可以自动生成 URL 模式,省去了手动配置的麻烦。

类型:
* ViewSet: 最基础的视图集,需要手动实现 list, retrieve 等方法。
* GenericViewSet: 继承自 ViewSetGenericAPIView,可以混合使用 mixins 来快速构建常用操作。
* ModelViewSet: 最常用的视图集,继承自 GenericViewSet 并混合了所有常用的 mixins (List, Create, Retrieve, Update, Destroy),可以直接与模型关联,实现完整的 CRUD 操作。

Router (路由器):
Router 负责将 ViewSet 自动注册到 URL 模式中。最常用的是 DefaultRouterSimpleRouter

示例:

“`python

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

urls.py (在你的 Django 项目的 urls.py 中)

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register(r’products’, ProductViewSet)

urlpatterns = [
path(‘api/’, include(router.urls)),
]
“`

通过上述配置,DefaultRouter 会自动为 ProductViewSet 生成以下 URL 模式:
* /api/products/ (GET, POST) -> list, create
* /api/products/{id}/ (GET, PUT, PATCH, DELETE) -> retrieve, update, partial_update, destroy

4. Authentication(认证)与 Permissions(权限)

DRF 提供了灵活的认证和权限系统来保护你的 API。

  • 认证 (Authentication): 识别用户的身份。DRF 支持多种认证方式:
    • BasicAuthentication: HTTP Basic 认证,通常用于测试或内部服务。
    • TokenAuthentication: 基于 Token 的认证,用户登录后获取 Token,后续请求在 Authorization 头中携带 Token。
    • SessionAuthentication: 基于 Session 的认证,通常用于与 Django 管理后台或基于浏览器的应用集成。
    • OAuth2Authentication: OAuth2 认证。
  • 权限 (Permissions): 决定用户是否有权执行某个操作。DRF 提供了多种权限类:
    • AllowAny: 允许所有用户访问。
    • IsAuthenticated: 只有认证用户才能访问。
    • IsAdminUser: 只有管理员用户才能访问。
    • IsAuthenticatedOrReadOnly: 认证用户可读写,未认证用户只读。
    • DjangoModelPermissions / DjangoObjectPermissions: 基于 Django 模型权限的权限。
    • 自定义权限: 可以通过继承 BasePermission 类来自定义复杂的权限逻辑。

示例:

“`python

settings.py

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’, # 全局启用 Token 认证
‘rest_framework.authentication.SessionAuthentication’,
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’, # 全局权限:认证用户可读写,匿名用户只读
]
}

views.py (局部覆盖)

from rest_framework.permissions import IsAdminUser

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAdminUser] # 只允许管理员进行所有操作
“`

5. Pagination(分页)与 Filtering(过滤)

DRF 提供了多种分页和过滤机制,用于处理大量数据。

  • 分页 (Pagination):

    • PageNumberPagination: 基于页码的分页。
    • LimitOffsetPagination: 基于限制(limit)和偏移(offset)的分页。
    • CursorPagination: 基于游标的分页,适用于大型数据集和连续滚动。
  • 过滤 (Filtering):

    • DjangoFilterBackend: 最常用的过滤后端,允许你基于模型字段进行过滤。需要安装 django-filter
    • SearchFilter: 提供一个搜索功能,根据指定的字段进行模糊匹配。
    • OrderingFilter: 允许客户端通过查询参数指定结果的排序方式。

示例:

“`python

settings.py

REST_FRAMEWORK = {
# … 其他设置
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’,
‘PAGE_SIZE’: 10, # 每页10条记录
‘DEFAULT_FILTER_BACKENDS’: [
‘django_filters.rest_framework.DjangoFilterBackend’,
‘rest_framework.filters.SearchFilter’,
‘rest_framework.filters.OrderingFilter’,
]
}

views.py

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = [‘in_stock’, ‘price’] # 允许按库存状态和价格过滤
search_fields = [‘name’, ‘description’] # 允许按名称和描述搜索
ordering_fields = [‘name’, ‘price’] # 允许按名称和价格排序
“`

二、DRF 实战:构建一个简单的产品 API

我们将从零开始,构建一个管理产品的 RESTful API。

1. 项目设置

首先,创建一个 Django 项目和一个应用:

bash
django-admin startproject myproject
cd myproject
python manage.py startapp products
pip install djangorestframework django-filter # 安装 DRF 和 django-filter

myproject/settings.py 中注册应用和 DRF:

“`python

myproject/settings.py

INSTALLED_APPS = [
# …
‘rest_framework’,
‘django_filters’, # 注册 django-filter
‘products’,
]

DRF 配置

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.SessionAuthentication’,
‘rest_framework.authentication.TokenAuthentication’, # 可选,如果需要基于 Token 的认证
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticatedOrReadOnly’,
],
‘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’,
]
}
“`

2. 定义模型 (products/models.py)

“`python

products/models.py

from django.db import models

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

class Meta:
    ordering = ['-created_at']

def __str__(self):
    return self.name

“`

运行数据库迁移:

bash
python manage.py makemigrations products
python manage.py migrate

3. 创建序列化器 (products/serializers.py)

“`python

products/serializers.py

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ‘all‘ # 包含所有字段
read_only_fields = [‘id’, ‘created_at’, ‘updated_at’] # 设置只读字段
“`

4. 创建视图集 (products/views.py)

“`python

products/views.py

from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import SearchFilter, OrderingFilter
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser

class ProductViewSet(viewsets.ModelViewSet):
“””
允许用户查看、编辑、创建和删除产品的 API 端点。
“””
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAuthenticatedOrReadOnly] # 认证用户可读写,匿名用户只读

# 局部配置过滤和搜索
filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
filterset_fields = ['in_stock', 'price']
search_fields = ['name', 'description']
ordering_fields = ['name', 'price', 'created_at']

# 如果需要更细粒度的权限,例如只有管理员才能创建/更新/删除
def get_permissions(self):
    if self.action in ['create', 'update', 'partial_update', 'destroy']:
        self.permission_classes = [IsAdminUser]
    else:
        self.permission_classes = [IsAuthenticatedOrReadOnly]
    return super().get_permissions()

“`

5. 配置 URL (myproject/urls.pyproducts/urls.py)

首先,在 products 应用下创建一个 urls.py 文件(如果不存在):

“`python

products/urls.py

from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register(r’products’, ProductViewSet, basename=’product’) # basename 是为了解决没有 queryset 的 ViewSet 的反向解析问题

urlpatterns = router.urls
“`

然后,在项目的主 urls.py 中包含这个应用的 URL:

“`python

myproject/urls.py

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

urlpatterns = [
path(‘admin/’, admin.site.urls),
path(‘api/’, include(‘products.urls’)), # 包含产品 API 的 URL
path(‘api-auth/’, include(‘rest_framework.urls’)), # 包含 DRF 提供的登录/登出 URL,用于 Browsable API
]
“`

6. 测试 API

运行开发服务器:

bash
python manage.py createsuperuser # 创建一个管理员用户用于测试
python manage.py runserver

打开浏览器,访问 http://127.0.0.1:8000/api/products/
如果一切正常,你将看到 DRF 提供的 Browsable API 界面,可以进行:
* 查看产品列表 (GET)
* 创建新产品 (POST) – 需要登录或使用管理员账户
* 访问 http://127.0.0.1:8000/api/products/1/ 查看、更新、删除单个产品

你也可以使用工具(如 Postman、Insomnia 或 curl)来测试 API。

示例 curl 命令:

  • 获取所有产品:
    bash
    curl http://127.0.0.1:8000/api/products/
  • 创建产品 (需要管理员身份或认证 Token):
    bash
    # 如果使用 Session 认证,需要先登录到 Browsable API
    # 如果使用 Token 认证,需要获取 Token 并替换 YOUR_AUTH_TOKEN
    curl -X POST -H "Content-Type: application/json" \
    -H "Authorization: Token YOUR_AUTH_TOKEN" \
    -d '{"name": "New Gadget", "description": "A cool new device.", "price": "99.99", "in_stock": true}' \
    http://127.0.0.1:8000/api/products/
  • 过滤产品 (例如,过滤库存中且价格低于 100 的产品):
    bash
    curl "http://127.0.0.1:8000/api/products/?in_stock=true&price__lt=100"
  • 搜索产品:
    bash
    curl "http://127.0.0.1:8000/api/products/?search=Gadget"
  • 排序产品:
    bash
    curl "http://127.0.0.1:8000/api/products/?ordering=-price" # 按价格降序

总结

Django REST Framework 通过其强大的序列化器、灵活的视图集和路由器、可插拔的认证/权限系统以及便捷的分页/过滤功能,极大地加速了 RESTful API 的开发。理解并熟练运用这些核心概念,将使你能够高效、优雅地构建高性能的 Web API。

这仅仅是 DRF 功能的冰山一角。你可以进一步探索自定义字段、验证器、解析器、渲染器、限流、信号、嵌套序列化器等高级特性,以满足更复杂的业务需求。

滚动至顶部