DRF 入门:了解 Django Rest Framework 的核心功能
前言
在当今互联互通的世界里,应用程序之间通过 API(应用程序接口)进行数据交换已成为常态。无论是移动应用、前端单页应用(SPA),还是其他后端服务,都需要一套高效、标准化的方式来暴露和消费数据。RESTful API 设计风格因其简洁、灵活和易于理解而广受欢迎。
Django 作为 Python 世界里最流行的 Web 框架之一,以其“快速开发、低代码量”的理念赢得了众多开发者青睐。然而,原生的 Django 视图(Views)主要面向 HTML 页面的渲染,虽然也能返回 JSON 等数据,但构建符合 RESTful 规范、功能完善(如序列化、反序列化、请求解析、响应渲染、认证、权限、限流等)的 API 端点则需要大量重复劳动。
正是在这样的背景下,Django REST Framework (DRF) 应运而生。它是 Django 的一个强大且灵活的扩展,专门用于构建 Web API。DRF 提供了一系列开箱即用的组件和工具,极大地简化了 RESTful API 的开发过程,让开发者能够专注于业务逻辑,而不是底层协议和繁琐的实现细节。
本文将带领初学者深入了解 DRF 的核心功能,包括序列化器(Serializers)、请求与响应(Requests & Responses)、视图与视图集(Views & Viewsets)、路由器(Routers)以及认证与权限(Authentication & Permissions)等,帮助你快速入门并掌握使用 DRF 构建强大 API 的基础。
为什么选择 Django REST Framework?
在深入核心功能之前,我们先快速了解一下 DRF 的主要优势:
- 强大而灵活的序列化功能: 轻松将 Django 模型或其他数据结构转换为 Python 原生类型,再渲染成 JSON、XML 等格式,反之亦然。
- 可定制的请求和响应处理: 提供统一的
Request
对象和Response
对象,方便处理各种数据格式和状态码。 - 丰富的视图类: 提供了从基础
APIView
到功能强大的ModelViewSet
等多种视图基类,覆盖了常见的 API 操作需求。 - 自动化的 URL 配置: Viewsets 结合 Routers 可以极大地简化 URL 路由的配置。
- 内置认证和权限系统: 提供了多种认证方式和权限策略,方便实现 API 的安全性控制。
- 可浏览器化的 API: 提供一个方便的浏览器界面,用于测试和交互 API,极大地提高了开发效率和易用性。
- 广泛的文档和社区支持: 作为 Django 生态系统中最受欢迎的库之一,DRF 拥有高质量的文档和活跃的社区。
简而言之,如果你需要使用 Django 构建 API,DRF 是你几乎必然会选择的利器。
准备工作:安装与设置
开始使用 DRF 前,你需要将其安装到你的 Django 项目中:
bash
pip install djangorestframework
然后,将 rest_framework
添加到你的 Django 项目的 settings.py
文件中的 INSTALLED_APPS
列表中:
“`python
settings.py
INSTALLED_APPS = [
# … 其他应用
‘rest_framework’,
# … 你的应用
]
“`
至此,DRF 就已成功集成到你的 Django 项目中,你可以开始使用它的各种功能了。
核心功能一:序列化器 (Serializers)
序列化器是 DRF 中最核心、最基础的概念之一,理解它至关重要。
问题: 为什么需要序列化器?
在 Django 中,你的数据通常存储在数据库中,通过 Django 模型(Models)来表示。但 API 通常需要在客户端(浏览器、移动 App 等)和服务器之间传输数据。这些数据通常是结构化的文本格式,如 JSON 或 XML。
- 从服务器到客户端: 你需要将 Django 模型对象转换为客户端能够理解和使用的数据格式(例如,将一个
Book
模型的实例转换为一个 JSON 字符串)。这个过程就是序列化 (Serialization)。 - 从客户端到服务器: 当客户端发送数据(例如,创建一个新的 Book 对象)时,这些数据通常是 JSON 或 XML 格式。你需要将这些结构化文本数据解析出来,验证其有效性,然后创建或更新相应的 Django 模型对象。这个过程就是反序列化 (Deserialization)。
序列化器正是用来处理这两个过程的工具。它定义了数据如何从复杂类型(如 Django 模型实例、QuerySet)转换为 Python 原生类型(如字典、列表),以及如何从 Python 原生类型转换回复杂类型,并在此过程中进行数据验证。
1. 基本序列化器 (Serializer)
rest_framework.serializers.Serializer
是序列化器的基类。它类似于 Django 的 forms.Form
或 modelforms.ModelForm
,定义了一组字段以及如何处理这些字段的数据。
假设我们有一个简单的 Django 模型:
“`python
models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField(null=True, blank=True)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
publication_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)
def __str__(self):
return self.title
“`
我们可以为 Book
模型创建一个基本的 Serializer
:
“`python
serializers.py
from rest_framework import serializers
from .models import Book, Author
class BookSerializer(serializers.Serializer):
# 定义序列化器字段,对应 Book 模型的一些属性
id = serializers.IntegerField(read_only=True) # read_only=True 表示该字段只用于序列化(输出),不用于反序列化(输入)
title = serializers.CharField(max_length=200)
author_id = serializers.PrimaryKeyRelatedField(queryset=Author.objects.all(), source=’author’, write_only=True) # 用于输入作者ID
author_name = serializers.CharField(source=’author.name’, read_only=True) # 用于输出作者姓名
publication_date = serializers.DateField()
isbn = serializers.CharField(max_length=13)
# 重写 create 方法处理反序列化时的对象创建
def create(self, validated_data):
# validated_data 包含了通过验证的数据
# 创建 Book 对象并返回
return Book.objects.create(**validated_data)
# 重写 update 方法处理反序列化时的对象更新
def update(self, instance, validated_data):
# instance 是要更新的 Book 对象
# validated_data 包含了通过验证的数据
instance.title = validated_data.get('title', instance.title)
instance.author = validated_data.get('author', instance.author) # 注意这里author_id通过source='author'映射到了author对象
instance.publication_date = validated_data.get('publication_date', instance.publication_date)
instance.isbn = validated_data.get('isbn', instance.isbn)
instance.save()
return instance
“`
使用序列化器:
-
序列化 (Python 对象 -> JSON):
“`python
views.py 或 shell 中
from .models import Book
from .serializers import BookSerializerbook = Book.objects.get(id=1) # 获取一个 Book 对象
serializer = BookSerializer(book) # 创建序列化器实例,传入要序列化的对象
data = serializer.data # 获取序列化后的数据 (Python 字典)print(data) # {‘id’: 1, ‘title’: ‘…’, ‘author_name’: ‘…’, …}
通常我们会使用 Response 对象将其渲染成 JSON
“`
-
序列化 (QuerySet -> JSON):
“`python
books = Book.objects.all() # 获取一个 QuerySetmany=True 参数表示处理多个对象(一个列表)
serializer = BookSerializer(books, many=True)
data = serializer.data # 获取序列化后的数据 (Python 字典列表)print(data) # [{‘id’: 1, …}, {‘id’: 2, …}, …]
“`
-
反序列化 (JSON -> Python 对象):
“`python
假设接收到的 JSON 数据
json_data = {‘title’: ‘New Book Title’, ‘author_id’: 1, ‘publication_date’: ‘2023-01-01’, ‘isbn’: ‘978-3-16-148410-0’}
serializer = BookSerializer(data=json_data) # 创建序列化器实例,传入要反序列化的数据
is_valid = serializer.is_valid() # 执行验证,返回 True 或 Falseif is_valid:
validated_data = serializer.validated_data # 获取验证通过的数据 (Python 字典)
# print(validated_data)
# 调用 create() 或 update() 方法保存对象
book_instance = serializer.save() # 调用 serializer.create() 或 serializer.update()
# print(book_instance) # 保存成功的 Book 对象
else:
errors = serializer.errors # 获取验证失败的错误信息 (Python 字典)
# print(errors) # {‘title’: [‘This field is required.’], …}
“`
可以看到,Serializer
提供了最大的灵活性,但需要手动定义字段并实现 create()
和 update()
方法。
2. 模型序列化器 (ModelSerializer)
对于与 Django 模型直接对应的 API,rest_framework.serializers.ModelSerializer
提供了巨大的便利。它会自动检查模型字段,并根据模型字段自动生成对应的序列化器字段,并默认实现了 create()
和 update()
方法。
使用 ModelSerializer
重写上面的 BookSerializer
:
“`python
serializers.py
from rest_framework import serializers
from .models import Book, Author
… AuthorSerializer if needed
class BookModelSerializer(serializers.ModelSerializer):
# ModelSerializer 会自动根据 Book 模型生成字段
# 但我们仍可以自定义字段或覆盖自动生成的字段
# 例如,添加一个只读的作者姓名字段
author_name = serializers.CharField(source=’author.name’, read_only=True)
# 例如,自定义 author 字段的显示方式(如果需要输出作者的完整信息)
# author = AuthorSerializer(read_only=True)
class Meta:
model = Book
# fields = '__all__' # 包含模型的所有字段
# 或者明确指定要包含的字段
fields = ['id', 'title', 'author', 'author_name', 'publication_date', 'isbn']
# read_only_fields = ['id'] # 将特定字段设置为只读
# 如果 fields='__all__', 可以在 extra_kwargs 中设置选项
extra_kwargs = {
'author': {'write_only': True} # 将作者字段设置为只用于输入(反序列化)
}
使用 ModelSerializer 与使用普通 Serializer 类似,只是定义方式更简洁
“`
在这个 BookModelSerializer
中:
- 我们指定了
model = Book
和fields = [...]
。DRF 会自动为title
,publication_date
,isbn
创建对应的序列化器字段。 id
字段通常是模型的自动生成主键,DRF 会自动将其包含并设置为read_only=True
。author
字段是 ForeignKey,ModelSerializer
默认会生成一个PrimaryKeyRelatedField
。我们通过extra_kwargs={'author': {'write_only': True}}
将其设置为只用于输入。- 我们手动添加了一个
author_name
字段,使用source='author.name'
从 related object 中获取数据,并设置为read_only=True
。
ModelSerializer
极大地减少了代码量,是处理模型数据时最常用的序列化器类型。
3. 序列化字段 (Serializer Fields)
序列化器由各种字段组成,这些字段定义了数据的类型、验证规则、以及如何映射到或从对象中获取数据。DRF 提供了丰富的字段类型:
CharField
,IntegerField
,BooleanField
,FloatField
,DateField
,DateTimeField
,TimeField
,DecimalField
,EmailField
,URLField
,UUIDField
等:对应各种基本数据类型。ChoiceField
: 处理有固定选项的字段。ListField
: 处理列表数据。DictField
: 处理字典数据。FileField
,ImageField
: 处理文件和图片上传。PrimaryKeyRelatedField
,HyperlinkedRelatedField
,SlugRelatedField
: 处理关系字段(ForeignKey, ManyToMany等),用于序列化关联对象的主键、超链接或 slug。SerializerMethodField
: 一个非常强大的字段,允许你自定义字段的输出值,通过定义一个与字段名同名的get_
方法来计算值。Nested Serializer
: 将另一个序列化器作为字段包含进来,用于嵌套序列化关联对象(例如,在 Book 序列化器中完整包含 Author 对象的序列化数据)。
“`python
嵌套序列化例子
class AuthorSerializer(serializers.ModelSerializer):
class Meta:
model = Author
fields = [‘id’, ‘name’]
class BookDetailSerializer(serializers.ModelSerializer):
author = AuthorSerializer(read_only=True) # 使用嵌套序列化器显示完整的作者信息
class Meta:
model = Book
fields = ['id', 'title', 'author', 'publication_date', 'isbn']
使用 BookDetailSerializer 序列化一个 Book 对象时,输出会包含 author 的详细信息
{ “id”: 1, “title”: “…”, “author”: { “id”: 1, “name”: “…” }, …}
“`
4. 数据验证 (Validation)
序列化器的一个重要功能是数据验证。当你调用 serializer.is_valid()
时,它会执行以下验证:
- 字段级别的验证: 每个字段都有内置的验证规则(例如,
CharField
的max_length
,DateField
的日期格式)。你也可以通过在序列化器类中定义validate_fieldname
方法来自定义特定字段的验证逻辑。 - 对象级别的验证: 你可以在序列化器类中定义
validate
方法,接收一个包含所有通过字段验证的数据的字典,进行跨字段或更复杂的验证。
“`python
serializers.py
class BookSerializerWithValidation(serializers.Serializer):
title = serializers.CharField(max_length=200)
publication_date = serializers.DateField()
# 字段级别的验证示例
def validate_title(self, value):
# 确保书名不包含敏感词
if "敏感词" in value:
raise serializers.ValidationError("书名不能包含敏感词")
return value
# 对象级别的验证示例
def validate(self, data):
# 确保出版日期不早于作者出生日期(假设作者已出生)
# 需要 access 到 author 对象,ModelSerializer 会更方便
# 这里只做日期自身的验证示例
publication_date = data.get('publication_date')
if publication_date and publication_date.year < 1900:
raise serializers.ValidationError("出版日期不能早于1900年")
return data
“`
serializer.is_valid()
验证失败时,serializer.errors
属性会返回一个字典,包含了字段名和对应的错误信息列表,这在 API 返回错误信息时非常有用。
核心功能二:请求 (Requests) 与响应 (Responses)
DRF 对 Django 原生的 HttpRequest
和 HttpResponse
进行了封装和增强,提供了更适合 API 开发的 Request
和 Response
对象。
1. 请求对象 (Request)
DRF 的 Request
对象封装了 Django 的 HttpRequest
,并增加了处理 API 数据(如解析请求体中的 JSON、XML 数据)的功能。你可以通过 request.data
属性方便地访问解析后的请求体数据(如 POST, PUT, PATCH 请求的数据),无论客户端发送的是 JSON、表单数据还是其他格式。
“`python
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class MyAPIView(APIView):
def post(self, request, format=None):
# 使用 request.data 访问请求体数据
# 如果客户端发送的是 JSON: {‘name’: ‘value’} -> request.data[‘name’]
# 如果客户端发送的是表单: name=value -> request.data[‘name’]
name = request.data.get(‘name’)
if name:
return Response({“message”: f”Received name: {name}”}, status=200)
else:
# request.query_params 访问 URL 查询参数 (?key=value)
query_name = request.query_params.get(‘name’)
if query_name:
return Response({“message”: f”Received name from query: {query_name}”}, status=200)
else:
return Response({“message”: “Name not provided”}, status=400)
def get(self, request, format=None):
# request.query_params 访问 GET 请求的 URL 查询参数
page = request.query_params.get('page', 1)
return Response({"message": f"GET request received, page: {page}"})
“`
request.data
属性是一个 QueryDict
或 Parser
解析后的字典,它会根据请求头的 Content-Type
自动解析请求体。request.query_params
属性用于访问 URL 中的查询参数(GET 请求)。
2. 响应对象 (Response)
DRF 的 Response
对象继承自 HttpResponse
,但它接受任意的 Python 原生数据类型(如字典、列表)作为其第一个参数,并根据协商的内容类型(Content Negotiation)自动将其渲染成客户端期望的格式(默认为 JSON)。你还可以方便地设置 HTTP 状态码。
“`python
views.py
from rest_framework.response import Response
from rest_framework import status # 导入常用的 HTTP 状态码常量
class AnotherAPIView(APIView):
def get(self, request, format=None):
data = {
“id”: 1,
“name”: “Example Item”,
“price”: 10.99
}
# 默认渲染为 JSON,状态码默认为 200 OK
return Response(data)
def post(self, request, format=None):
# 假设处理请求并创建了一个新资源
success = True # 示例
if success:
created_item_data = {"id": 2, "name": "Created Item"}
# 返回 201 Created 状态码
return Response(created_item_data, status=status.HTTP_201_CREATED)
else:
error_message = {"error": "Failed to create item"}
# 返回 400 Bad Request 状态码
return Response(error_message, status=status.HTTP_400_BAD_REQUEST)
“`
使用 Response
对象,你不再需要手动导入 JsonResponse
或进行 JSON 序列化,DRF 会为你处理这一切。rest_framework.status
模块提供了各种 HTTP 状态码的常量,推荐使用它们来提高代码的可读性。
核心功能三:视图 (Views) 与视图集 (Viewsets)
视图(或视图函数/类)是处理 HTTP 请求并返回响应的核心。DRF 提供了多种视图基类,以满足不同复杂度的需求。
1. APIView
rest_framework.views.APIView
是 DRF 提供的最基础的视图类。它类似于 Django 的 django.views.View
,但提供了 DRF 特有的功能,如:
- 使用 DRF 的
Request
对象。 - 返回 DRF 的
Response
对象。 - 进行认证、权限、限流等检查。
- 执行内容协商。
你可以通过定义与 HTTP 方法同名的方法(get
, post
, put
, patch
, delete
等)来处理不同的请求。
“`python
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer # 假设我们用回基础 BookSerializer
class BookListCreateAPIView(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() # 调用 BookSerializer 的 create() 方法
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class BookDetailAPIView(APIView):
“””
检索、更新或删除一本特定的书籍
“””
def get_object(self, pk):
try:
return Book.objects.get(pk=pk)
except Book.DoesNotExist:
raise Http404 # DRF 会将其转换为 404 Response
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) # 传入 instance 和 data
if serializer.is_valid():
serializer.save() # 调用 BookSerializer 的 update() 方法
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()
# 返回 204 No Content 表示删除成功且无返回内容
return Response(status=status.HTTP_204_NO_CONTENT)
“`
使用 APIView
需要为每个 HTTP 方法编写相应的逻辑,并手动处理对象的获取、序列化、验证和保存等步骤。这提供了很大的灵活性,但对于常见的 CRUD(创建、读取、更新、删除)操作,会显得重复。
2. 通用视图 (GenericAPIView) 与 Mixins
为了减少重复代码,DRF 提供了 rest_framework.generics.GenericAPIView
。它提供了处理模型查询集和序列化器的基础功能,如 get_queryset()
和 get_serializer_class()
方法。
更重要的是,DRF 提供了一系列混入类 (Mixins),它们实现了常见的 API 操作逻辑,如列表、创建、检索、更新、删除。你可以将这些 Mixins 与 GenericAPIView
结合使用,快速构建视图。
常用的 Mixins:
ListModelMixin
: 实现list()
方法,用于获取列表数据。CreateModelMixin
: 实现create()
方法,用于创建新对象。RetrieveModelMixin
: 实现retrieve()
方法,用于获取单个对象。UpdateModelMixin
: 实现update()
方法,用于更新对象。DestroyModelMixin
: 实现destroy()
方法,用于删除对象。
结合 GenericAPIView
和 Mixins:
“`python
views.py
from rest_framework import generics
from .models import Book
from .serializers import BookModelSerializer # 假设我们使用 ModelSerializer
列表和创建视图
class BookListCreateGenericView(generics.ListModelMixin, generics.CreateModelMixin, generics.GenericAPIView):
queryset = Book.objects.all() # 指定查询集
serializer_class = BookModelSerializer # 指定序列化器类
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs) # 调用 ListModelMixin 的 list 方法
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs) # 调用 CreateModelMixin 的 create 方法
检索、更新和删除视图
class BookDetailGenericView(generics.RetrieveModelMixin, generics.UpdateModelMixin, generics.DestroyModelMixin, generics.GenericAPIView):
queryset = Book.objects.all() # 指定查询集
serializer_class = BookModelSerializer # 指定序列化器类
# lookup_field = ‘pk’ # 默认就是 pk,如果你的 URL 参数是其他字段名,需要指定
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs) # 调用 RetrieveModelMixin 的 retrieve 方法
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs) # 调用 UpdateModelMixin 的 update 方法
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs) # update 方法也支持 partial_update
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs) # 调用 DestroyModelMixin 的 destroy 方法
“`
这种方式通过组合 Mixins 实现了特定的功能组合(例如,列表+创建,或检索+更新+删除),代码量比 APIView
大大减少。DRF 还提供了一些预先组合好的通用视图类,如 ListAPIView
, CreateAPIView
, RetrieveAPIView
, UpdateAPIView
, DestroyAPIView
, ListCreateAPIView
, RetrieveUpdateAPIView
, RetrieveDestroyAPIView
, RetrieveUpdateDestroyAPIView
等,它们是 GenericAPIView
和相应 Mixins 的直接组合,使用起来更方便。
例如,BookListCreateGenericView
可以直接写成:
“`python
from rest_framework import generics
class BookListCreateGenericView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
class BookDetailGenericView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
“`
这样代码就非常简洁了!
3. 视图集 (Viewsets)
Viewsets (视图集) 是 DRF 中进一步抽象的概念。它不直接提供 get
, post
等方法,而是提供了一组操作(actions),如 list
, create
, retrieve
, update
, partial_update
, destroy
。一个 Viewset 可以看作是一组相关视图逻辑的集合。
Viewsets 的主要优势在于,它与路由器 (Routers) 结合使用时,可以自动生成 URL 配置,极大地简化了 urls.py
文件。
rest_framework.viewsets.ViewSet
是最基础的视图集,类似于 APIView
。而 rest_framework.viewsets.ModelViewSet
是最常用的视图集,它继承自 GenericAPIView
并混入了所有常用的 Mixins (ListModelMixin
, CreateModelMixin
, RetrieveModelMixin
, UpdateModelMixin
, DestroyModelMixin
)。这意味着 ModelViewSet
开箱即用地提供了对模型进行完整 CRUD 操作的 API 端点。
“`python
views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookModelSerializer
使用 ModelViewSet
class BookViewSet(viewsets.ModelViewSet):
“””
提供了对 Book 模型的 ‘list’, ‘create’, ‘retrieve’, ‘update’, ‘partial_update’, ‘destroy’ 操作
“””
queryset = Book.objects.all()
serializer_class = BookModelSerializer
# ModelViewSet 会自动提供上面这些操作,不需要手动定义 get/post 等方法
# 你可以覆盖这些方法来自定义行为,例如 def list(self, request, args, *kwargs): …
“`
Viewsets 本身不会直接响应请求,它们需要与路由器结合才能生成 URL 模式。
核心功能四:路由器 (Routers)
路由器负责将 Viewsets 中的操作(actions)映射到具体的 URL 路径和 HTTP 方法上。使用路由器可以避免手动为 Viewset 的每个操作编写 URL 模式,尤其是在使用 ModelViewSet
时,路由器能自动生成一套标准的 CRUD API URL。
DRF 提供了两种主要的路由器:
SimpleRouter
: 提供标准的列表和详情路由。DefaultRouter
: 在SimpleRouter
的基础上增加了 API 根视图和格式后缀。
使用路由器配置 URL:
“`python
urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from . import views # 导入你的 views.py
创建一个路由器实例
router = DefaultRouter()
注册 Viewset 到路由器
prefix 是 URL 前缀, viewset 是对应的 Viewset 类, basename 是用于生成 URL 名称的基础
router.register(r’books’, views.BookViewSet, basename=’book’)
router.register(r’authors’, views.AuthorViewSet, basename=’author’) # 如果有 AuthorViewSet
路由器会自动生成 URL 模式
例如,对于 BookViewSet,DefaultRouter 会生成以下 URL 模式:
/books/ -> list (GET), create (POST)
/books/{pk}/ -> retrieve (GET), update (PUT), partial_update (PATCH), destroy (DELETE)
/books/{pk}.json -> retrieve (GET, JSON format)
/books/.json -> list (GET, JSON format)
等等…
urlpatterns = [
# … 其他 URL 模式
path(‘api/’, include(router.urls)), # 将路由器生成的 URL 模式包含进来
# path(‘api-auth/’, include(‘rest_framework.urls’, namespace=’rest_framework’)), # 可选:登录/退出视图,用于浏览器化API
]
“`
通过路由器,你只需要一行 router.register()
代码,就为 BookViewSet
配置了所有常见的 API 端点,极大地提高了开发效率。对于初学者来说,理解 Viewset 和 Router 的配合是掌握 DRF 的一个重要步骤。
核心功能五:认证 (Authentication) 与权限 (Permissions)
API 的安全性至关重要。DRF 提供了灵活的认证和权限系统来控制谁可以访问你的 API 以及他们可以执行哪些操作。
1. 认证 (Authentication)
认证是验证请求发送者身份的过程,即“你是谁?”。DRF 提供了多种认证类:
rest_framework.authentication.SessionAuthentication
: Django 会话认证,通常用于浏览器环境。rest_framework.authentication.BasicAuthentication
: HTTP Basic Auth,发送 Base64 编码的用户名和密码。不安全,仅用于测试或配合 HTTPS。rest_framework.authentication.TokenAuthentication
: 基于 Token 的认证,客户端发送请求时在头部携带一个 Token。常见且推荐的 API 认证方式。rest_framework.authentication.RemoteUserAuthentication
: 使用 Web 服务器提供的认证。- 自定义认证类:可以根据需求实现自己的认证逻辑。
认证类在接收到请求时运行。如果认证成功,request.user
会被设置为对应的用户对象,request.auth
会被设置为认证凭据(如 Token 对象)。
2. 权限 (Permissions)
权限是在身份验证成功后,确定用户是否有权执行请求的操作,即“你被允许做什么?”。认证只识别用户身份,权限才决定访问控制。
DRF 提供了多种权限类:
rest_framework.permissions.AllowAny
: 允许任何用户访问,无论是否认证。rest_framework.permissions.IsAuthenticated
: 只允许认证用户访问。rest_framework.permissions.IsAdminUser
: 只允许管理员用户 (user.is_staff
is True) 访问。rest_framework.permissions.IsAuthenticatedOrReadOnly
: 允许认证用户进行任何操作,未认证用户只允许读取(GET, HEAD, OPTIONS)操作。rest_framework.permissions.DjangoModelPermissions
: 使用 Django 的模型权限系统 (user.has_perm
)。rest_framework.permissions.DjangoObjectPermissions
: 使用 Django 的对象级别权限系统(需要第三方库如django-guardian
)。- 自定义权限类:可以实现
has_permission(self, request, view)
和has_object_permission(self, request, view, obj)
方法来定义复杂的权限规则。
配置认证和权限:
你可以在全局 settings.py
中配置默认的认证和权限类:
“`python
settings.py
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’,
‘rest_framework.authentication.SessionAuthentication’, # 可选,用于浏览器化 API
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’, # 默认只允许认证用户访问
# 或者 ‘rest_framework.permissions.AllowAny’, # 默认允许所有人访问
],
# 其他 DRF 设置…
}
“`
或者在单个视图或视图集中配置:
“`python
views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny
class ProtectedView(APIView):
# 配置该视图的认证类,覆盖全局设置
authentication_classes = [TokenAuthentication] # 假设已导入 TokenAuthentication
# 配置该视图的权限类,覆盖全局设置
permission_classes = [IsAuthenticated] # 只允许认证用户访问
def get(self, request):
content = {'message': '这是只有认证用户才能看到的秘密!'}
return Response(content)
class AdminOnlyView(APIView):
permission_classes = [IsAdminUser] # 只允许管理员访问
def post(self, request):
# ... 管理员操作逻辑 ...
content = {'message': '这是只有管理员才能执行的操作!'}
return Response(content)
在 Viewset 中配置
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookModelSerializer
permission_classes = [IsAuthenticatedOrReadOnly] # 认证用户可读写,未认证用户只读
# 也可以对 Viewset 中的特定 action 设置权限
# @action(detail=False, methods=['post'], permission_classes=[IsAdminUser])
# def import_books(self, request):
# ... 只有管理员能批量导入书籍 ...
“`
权限类会依次检查,只要有一个权限类返回 True
,就允许访问(对于 OR
逻辑)。如果是 AND
逻辑(列表中的所有权限类都必须通过),DRF 会检查列表中的每一个权限类,只有所有权限类都通过时才允许访问。如果任何一个权限类检查失败,都会返回 HTTP 403 Forbidden
响应。
其他重要的 DRF 功能
除了上述核心功能,DRF 还提供了许多其他有用的功能,可以大大提升 API 的质量和开发效率:
- 渲染器 (Renderers) 和解析器 (Parsers): 控制 API 响应的数据格式(如 JSON, XML, HTML)和请求体的解析方式。
JSONRenderer
和JSONParser
是默认配置,但可以轻松支持其他格式。浏览器化 API 就利用了HTMLFormRenderer
和BrowsableAPIRenderer
。 - 分页 (Pagination): 处理大型数据集的 API 返回。DRF 提供了多种分页类,如
PageNumberPagination
(基于页码) 和LimitOffsetPagination
(基于偏移量和限制数),可以方便地集成到 Generic Views 或 Viewsets 中。 - 过滤 (Filtering) 和搜索 (Searching): 允许客户端通过 URL 参数过滤或搜索数据集。DRF 支持
django-filter
库进行强大的过滤功能,并内置了简单的搜索功能。 - 版本控制 (Versioning): 支持在同一 API 中管理不同版本,如通过 URL (
/v1/books/
) 或请求头 (Accept: application/json; version=1.0
)。 - 限流 (Throttling): 控制客户端在一定时间内可以发出的请求数量,防止滥用。
- 测试 (Testing): DRF 提供了
APIClient
和APITestCase
等工具,方便进行 API 功能测试。 - 文档生成: 可以与
drf-yasg
或drf-spectacular
等第三方库集成,自动生成 OpenAPI (Swagger) 文档。
这些功能虽然不是最基础的“核心”,但在实际项目开发中非常常用且重要。掌握它们能让你构建更完善、更易用的 API。
总结
Django REST Framework 是一个强大、灵活且功能丰富的库,它是使用 Django 构建 Web API 的事实标准。本文详细介绍了 DRF 的几个核心功能:
- 序列化器 (Serializers): 负责 Python 对象与 API 数据格式(如 JSON)之间的转换和数据验证,其中
ModelSerializer
是最常用的工具。 - 请求与响应 (Requests & Responses): DRF 提供了增强的
Request
和Response
对象,简化了请求数据解析和响应数据渲染。 - 视图与视图集 (Views & Viewsets): 从基础的
APIView
到结合 Mixins 的GenericAPIView
,再到高度抽象的ModelViewSet
,DRF 提供了不同层次的视图抽象,帮助开发者高效地实现 API 逻辑。 - 路由器 (Routers): 与 Viewsets 配合,自动化地生成 URL 配置,尤其是
ModelViewSet
与DefaultRouter
的组合,可以快速搭建一套完整的 RESTful API 端点。 - 认证 (Authentication) 与权限 (Permissions): 构建安全 API 的基础,用于验证用户身份和控制访问权限。
掌握这些核心概念是入门 DRF 的关键。通过序列化器处理数据格式和验证,通过视图/视图集处理请求逻辑,通过路由器配置 URL,通过认证和权限保护你的 API。
本文只是 DRF 入门的敲门砖。DRF 还有许多高级特性和配置选项等待你去探索。最好的学习方式是动手实践,创建一个简单的 Django 项目,安装 DRF,并尝试使用 ModelSerializer
和 ModelViewSet
构建一个简单的图书管理 API。结合官方文档,你将能够逐步深入,成为一名熟练的 DRF 开发者。
祝你 DRF 学习之旅愉快!