深入浅出 Django REST Framework:核心概念解析 – wiki词典

深入浅出 Django REST Framework:核心概念解析

引言

在当今高度互联的软件世界中,API(应用程序编程接口)扮演着至关重要的角色。无论是为移动应用提供数据、驱动前端单页应用(SPA),还是实现系统间的数据交换,API 都是现代 Web 开发的基石。而 Django REST Framework(DRF)正是 Django 生态系统中构建强大、灵活且高效 RESTful API 的首选框架。

DRF 在 Django 坚实的基础上,提供了丰富的工具和约定,极大地简化了 API 的开发过程。它不仅处理了序列化、视图逻辑和认证等核心问题,还提供了浏览器可浏览 API、各种认证/权限方案、分页和过滤等高级功能。

本文将带您深入了解 Django REST Framework 的核心概念,帮助您理解其工作原理,并为您的 API 开发之旅打下坚实的基础。

1. 序列化器(Serializers)

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

核心功能:

  • 序列化 (Serialization): 将模型实例转换为可传输的数据格式(如字典)。
  • 反序列化 (Deserialization): 将接收到的数据验证并转换为模型实例。
  • 数据验证 (Validation): 在数据保存到数据库之前,对数据进行校验。

类型:

  • Serializer: 最基础的序列化器,用于自定义字段和验证逻辑。
  • ModelSerializer: DRF 提供的强大抽象,它会自动从 Django 模型中推断字段,并提供 create()update() 方法,类似于 Django 的 ModelForm

示例:

“`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)
description = models.TextField()
is_available = 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’, ‘price’, ‘description’, ‘is_available’]
# 或者使用 fields = ‘all‘ 包含所有字段
# read_only_fields = [‘id’] # 示例:指定只读字段
“`

2. 视图(Views)

DRF 的视图层与 Django 的视图类似,但它们被设计用于处理 API 请求和响应。DRF 提供了多种视图类型,以适应不同的开发需求。

2.1 APIView

APIView 是 DRF 提供的最基础的视图类,它继承自 Django 的 View,并添加了 DRF 特有的功能,如:

  • 请求(Request)对象: DRF 的 Request 对象扩展了 Django 的 HttpRequest,提供了更灵活的请求解析(支持 JSON、XML 等)。
  • 响应(Response)对象: DRF 的 Response 对象封装了内容协商和渲染过程。
  • 认证、权限和节流: 提供了配置认证、权限和节流策略的机制。

您可以使用 HTTP 方法(get, post, put, delete 等)来组织代码,类似于 Django 的类视图。

示例:

“`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 ProductList(APIView):
def get(self, request):
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)

def post(self, request):
    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)

“`

2.2 GenericAPIView

GenericAPIViewAPIView 的一个扩展,它包含了常用的列表和详情操作所需的核心功能,如:

  • queryset: 用于查找对象的查询集。
  • serializer_class: 用于序列化和反序列化的序列化器类。
  • lookup_field: 用于单个实例查找的字段(默认为 pk)。
  • get_object(), get_queryset(), get_serializer() 等辅助方法。

它本身并不提供具体的 HTTP 方法实现,而是设计为与其他 Mixins(如 ListModelMixin, RetrieveModelMixin 等)结合使用,以实现 RESTful 风格的通用操作。

2.3 混合类(Mixins)

DRF 提供了一组混合类,可以与 GenericAPIView 结合使用,快速构建常用操作:

  • ListModelMixin: 实现列表(GET)操作。
  • CreateModelMixin: 实现创建(POST)操作。
  • RetrieveModelMixin: 实现检索单个实例(GET)操作。
  • UpdateModelMixin: 实现更新(PUT/PATCH)操作。
  • DestroyModelMixin: 实现删除(DELETE)操作。

示例(结合 GenericAPIView 和 Mixins):

“`python
from rest_framework import generics, mixins

class ProductListCreate(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer

def get(self, request, *args, **kwargs):
    return self.list(request, *args, **kwargs)

def post(self, request, *args, **kwargs):
    return self.create(request, *args, **kwargs)

class ProductRetrieveUpdateDestroy(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer

def get(self, request, *args, **kwargs):
    return self.retrieve(request, *args, **kwargs)

def put(self, request, *args, **kwargs):
    return self.update(request, *args, **kwargs)

def delete(self, request, *args, **kwargs):
    return self.destroy(request, *args, **kwargs)

“`

2.4 通用视图(Generic Views)

为了进一步简化开发,DRF 提供了预先组合好的通用视图,它们直接继承自 GenericAPIView 和相应的 Mixins。

  • ListAPIView: 只读列表视图。
  • CreateAPIView: 只写创建视图。
  • ListCreateAPIView: 列表和创建视图。
  • RetrieveAPIView: 只读详情视图。
  • UpdateAPIView: 只写更新视图。
  • DestroyAPIView: 只写删除视图。
  • RetrieveUpdateAPIView: 详情和更新视图。
  • RetrieveDestroyAPIView: 详情和删除视图。
  • RetrieveUpdateDestroyAPIView: 详情、更新和删除视图(最常用)。

示例(使用通用视图):

“`python
from rest_framework import generics

class ProductListCreate(generics.ListCreateAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer

class ProductRetrieveUpdateDestroy(generics.RetrieveUpdateDestroyAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
“`

2.5 视图集(ViewSets)和路由器(Routers)

视图集(ViewSet)是 DRF 提供的一种更高级别的抽象,它将一组相关的视图逻辑(如列表、创建、检索、更新、删除)打包到一个类中。ViewSet 不直接提供 HTTP 方法处理,而是通过 .as_view() 方法在 URL 配置时映射到具体的 HTTP 方法。

类型:

  • ViewSet: 最基础的视图集。
  • GenericViewSet: 类似于 GenericAPIView,可以与 Mixins 结合。
  • ModelViewSet: 最常用的视图集,直接提供了一个模型的完整 CRUD 操作,类似于 RetrieveUpdateDestroyAPIViewListCreateAPIView 的组合。

路由器(Routers) 是 DRF 的另一大亮点,它能自动为 ViewSet 生成 URL 配置,极大地简化了 URL 的管理。

示例:

“`python

views.py

from rest_framework import viewsets

class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer

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(”, include(router.urls)),
]
``
使用
ModelViewSetDefaultRouter,你只需几行代码就能为Product` 模型创建一个功能完备的 RESTful API。

3. 请求(Request)与响应(Response)对象

3.1 Request 对象

DRF 的 Request 对象封装了 Django 的 HttpRequest,提供了更强大的功能:

  • request.data: 智能地处理传入的请求体。无论是 JSON、XML 还是表单数据,request.data 都能正确解析并返回一个 Python 字典(或类似字典的对象)。
  • request.query_params: 等同于 Django 的 request.GET,用于获取 URL 查询参数。
  • 认证信息: 包含了认证用户 (request.user) 和认证凭证 (request.auth)。

3.2 Response 对象

DRF 的 Response 对象是 TemplateResponse 的子类,用于处理 API 响应:

  • 它接受原生 Python 数据(如字典或列表)。
  • 根据客户端请求的 Accept 头自动进行内容协商,将数据渲染成 JSON、XML 等格式。
  • 可以轻松设置 HTTP 状态码。

示例:

“`python
from rest_framework.response import Response
from rest_framework import status

def some_api_view(request):
if request.method == ‘GET’:
data = {‘message’: ‘Hello from DRF API’}
return Response(data, status=status.HTTP_200_OK)
elif request.method == ‘POST’:
# request.data 会自动解析请求体
received_data = request.data
if ‘name’ in received_data:
return Response({‘received’: received_data[‘name’]}, status=status.HTTP_201_CREATED)
return Response({‘error’: ‘Name field missing’}, status=status.HTTP_400_BAD_REQUEST)
“`

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

安全是 API 开发的关键。DRF 提供了一套灵活的认证和权限系统。

4.1 认证(Authentication)

认证是确定客户端身份的过程。DRF 提供了多种认证方式:

  • SessionAuthentication: 基于 Django 会话的认证,适用于与浏览器前端结合使用。
  • BasicAuthentication: HTTP Basic 认证,通过用户名和密码进行认证。
  • TokenAuthentication: 基于 Token 的认证,客户端在每个请求头中发送一个 Token。
  • OAuth2Authentication (第三方包): OAuth2 是一种广泛使用的授权框架。

您可以在全局设置中配置默认认证类,也可以在单个视图或视图集上指定:

“`python

settings.py

REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’,
‘rest_framework.authentication.SessionAuthentication’,
],
# …
}

views.py

from rest_framework.authentication import TokenAuthentication, SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response

class ProtectedView(APIView):
authentication_classes = [TokenAuthentication, SessionAuthentication] # 视图级别配置
permission_classes = [IsAuthenticated]

def get(self, request):
    return Response({"message": f"Hello, {request.user.username}! You are authenticated."})

“`

4.2 权限(Permissions)

权限是在客户端身份确定后,决定其是否被允许执行特定操作(如读取、修改、删除)的过程。DRF 提供了多种权限类:

  • AllowAny: 允许所有用户访问(默认)。
  • IsAuthenticated: 只允许认证用户访问。
  • IsAdminUser: 只允许管理员用户访问。
  • IsAuthenticatedOrReadOnly: 认证用户可以读写,未认证用户只能读。
  • DjangoModelPermissions / DjangoObjectPermissions: 基于 Django 模型权限的权限控制。

您也可以创建自定义权限类,继承 BasePermission 并重写 has_permission 和/或 has_object_permission 方法。

5. 分页(Pagination)

当 API 返回大量数据时,分页是必不可少的功能,它可以限制每个响应返回的数据量,提高性能并改善用户体验。DRF 提供了多种分页器:

  • PageNumberPagination: 最简单的分页方式,通过页码来导航。
  • LimitOffsetPagination: 通过 limit(每页数量)和 offset(偏移量)参数来分页。
  • CursorPagination: 基于游标的分页,适用于大型数据集,能够更高效地处理动态数据插入和删除。

您可以在全局设置中配置默认分页器,或在视图上指定。

示例:

“`python

settings.py

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

views.py

from rest_framework import generics
from rest_framework.pagination import LimitOffsetPagination # 视图级别覆盖

class CustomPagination(LimitOffsetPagination):
default_limit = 5
max_limit = 20

class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = CustomPagination # 视图级别指定分页器
“`

6. 过滤(Filtering)

过滤允许客户端根据特定条件缩小 API 响应中包含的数据范围。DRF 可以与 django-filter 库无缝集成,提供强大的过滤功能。

示例:

  1. 安装 django-filter:
    bash
    pip install django-filter
  2. 添加到 INSTALLED_APPS:
    “`python
    # settings.py
    INSTALLED_APPS = [
    # …
    ‘django_filters’,
    # …
    ]

    REST_FRAMEWORK = {
    ‘DEFAULT_FILTER_BACKENDS’: [
    ‘django_filters.rest_framework.DjangoFilterBackend’
    ],
    # …
    }
    3. **创建 FilterSet:**python

    filters.py (或直接在 views.py 中定义)

    import django_filters
    from .models import Product

    class ProductFilter(django_filters.FilterSet):
    min_price = django_filters.NumberFilter(field_name=”price”, lookup_expr=’gte’)
    max_price = django_filters.NumberFilter(field_name=”price”, lookup_expr=’lte’)
    name_contains = django_filters.CharFilter(field_name=”name”, lookup_expr=’icontains’)

    class Meta:
        model = Product
        fields = ['is_available', 'name'] # 允许通过 name 和 is_available 精确过滤
    

    4. **在视图中使用:**python

    views.py

    from rest_framework import generics
    from django_filters.rest_framework import DjangoFilterBackend
    from .filters import ProductFilter # 导入之前定义的过滤器

    class ProductFilterList(generics.ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = [DjangoFilterBackend] # 指定过滤后端
    filterset_class = ProductFilter # 指定要使用的 FilterSet 类
    # 也可以直接通过 fields 属性指定模型字段进行过滤:
    # filterset_fields = [‘is_available’, ‘name’]
    “`

现在,您可以像这样进行过滤:/products/?is_available=true&min_price=10.00&name_contains=apple

结论

Django REST Framework 提供了一套全面而强大的工具集,用于构建高效、可维护的 RESTful API。通过理解并掌握其核心概念——序列化器、灵活的视图(从 APIViewModelViewSet)、请求/响应对象、认证与权限、分页和过滤,您将能够轻松地构建出满足各种需求的 API。

DRF 的设计哲学是”约定优于配置”,这意味着在许多情况下,您只需少量代码就能实现复杂的功能。此外,其强大的可扩展性允许您根据项目的具体需求定制每一个组件。

希望本文能帮助您对 Django REST Framework 的核心概念有了深入的理解。现在,是时候将这些知识付诸实践,开始构建您自己的强大 API 了!

滚动至顶部