Django REST Framework 入门指南:构建强大的 Web API
欢迎来到 Django REST Framework (DRF) 的世界!如果你是一名 Django 开发者,渴望构建一个强大、灵活且易于维护的 Web API,那么 DRF 无疑是你最得力的助手。它基于 Django 的强大基础之上,提供了一系列工具,极大地简化了构建 RESTful API 的过程。
本指南将带你从零开始,逐步深入 DRF 的核心概念,包括序列化器(Serializers)、视图(Views)、URL 路由(URLs)、身份认证(Authentication)、权限(Permissions)等,最终帮助你使用 DRF 搭建起一个功能完备的基础 API。
为什么选择 Django REST Framework?
在深入学习之前,我们先来了解一下 DRF 为什么如此受欢迎:
- 基于 Django 的强大生态: 如果你熟悉 Django,你会发现 DRF 的结构和设计理念与 Django 高度一致,学习曲线平缓。你可以直接利用 Django 已有的 Model、ORM、Settings 等功能。
- 序列化器 (Serializers): 轻松处理复杂数据的序列化(将数据库对象转换为 JSON/XML 等格式)和反序列化(将接收到的 JSON/XML 数据转换为 Python 对象并进行验证)。这是构建 API 的核心需求。
- 可浏览的 API (Browsable API): DRF 提供了一个非常友好的 Web 界面,允许你在浏览器中直接与 API 交互,测试端点,查看输入/输出,这极大地提高了开发效率和调试便利性。
- 丰富的视图类 (Views): 提供了通用的视图类(Generic Views)和视图集(ViewSets),可以快速实现常见的 CRUD (Create, Retrieve, Update, Delete) 操作,避免编写大量重复代码。
- 灵活的认证和权限系统 (Authentication & Permissions): 内置支持多种认证方案(如 Session、Token、JWT)和权限控制,可以轻松地保护你的 API。
- 强大的功能扩展: 内置了分页 (Pagination)、过滤 (Filtering)、搜索 (Search)、限流 (Throttling)、版本控制 (Versioning) 等常用 API 功能。
- 广泛的社区支持: 作为一个流行框架,DRF 拥有庞大的社区,遇到问题很容易找到解决方案和资源。
总之,DRF 提供了构建 Web API 所需的几乎所有工具,让你能够专注于业务逻辑而非底层实现细节。
前提条件
在开始本指南之前,你需要:
- 对 Python 语言有基本了解。
- 已经安装了 Python 和 pip。
- 对 Django 框架有基本认识,包括如何创建项目和应用、定义 Models、运行迁移等。
环境搭建和项目初始化
首先,我们需要创建一个 Django 项目并安装 DRF。
-
创建虚拟环境(推荐):
“`bash
python -m venv venv
source venv/bin/activate # macOS/Linuxvenv\Scripts\activate # Windows
“`
-
安装 Django 和 Django REST Framework:
bash
pip install django djangorestframework -
创建 Django 项目:
bash
django-admin startproject myapi_project .注意
.
表示在当前目录下创建项目,方便管理。 -
创建 Django 应用:
我们创建一个名为
products
的应用来管理商品数据。bash
python manage.py startapp products -
注册应用和 DRF:
打开
myapi_project/settings.py
文件,在INSTALLED_APPS
列表中添加'rest_framework'
和'products'
。“`python
myapi_project/settings.py
INSTALLED_APPS = [
‘django.contrib.admin’,
‘django.contrib.auth’,
‘django.contrib.contenttypes’,
‘django.contrib.sessions’,
‘django.contrib.messages’,
‘django.contrib.staticfiles’,
# Third-party apps
‘rest_framework’, # <– 添加 DRF# Local apps 'products', # <-- 添加你的应用
]
… 其他配置保持不变
“`
至此,我们的环境已经搭建完毕,DRF 也已经成功集成到 Django 项目中。
第一步:定义 Model
为了演示,我们在 products
应用中定义一个简单的 Product
Model。
打开 products/models.py
文件:
“`python
products/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=100, unique=True)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
“`
定义好 Model 后,别忘了进行数据库迁移:
bash
python manage.py makemigrations
python manage.py migrate
现在,我们的数据库中就有了 Product
表。你可以通过 Django Admin 添加一些示例数据方便后续测试。
第二步:创建 Serializer
Serializer 是 DRF 中一个非常核心的概念。它的主要作用有两个:
- 序列化 (Serialization): 将复杂的 Python 数据类型(如 Django Model 实例或 QuerySet)转换为易于通过网络传输的格式(如 JSON)。
- 反序列化 (Deserialization): 将接收到的低级数据(如 JSON 格式的请求体)解析并转换为 Python 对象,并对数据的有效性进行验证。
对于 Django Model,DRF 提供了 ModelSerializer
类,可以自动为你生成基于 Model 字段的 Serializer,极大地简化了代码。
在 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‘ # 表示序列化 Model 中的所有字段
# 或者你可以明确指定需要序列化的字段:
# fields = [‘id’, ‘name’, ‘description’, ‘price’, ‘stock’]
# 或者排除某些字段:
# exclude = [‘created_at’, ‘updated_at’]
“`
这里,我们创建了一个 ProductSerializer
,它继承自 serializers.ModelSerializer
。在内部的 Meta
类中,我们指定了要关联的 Model (Product
) 和需要序列化的字段 (__all__
表示所有字段)。
这个 Serializer 现在可以:
- 接收一个
Product
实例或 QuerySet,并将其转换为字典,然后 DRF 会将其渲染成 JSON。 - 接收一个字典(通常来自请求体),验证其字段是否与
Product
Model 匹配,如果有效,可以用来创建或更新Product
实例。
第三步:创建 View
在 Django 中,View 负责接收 HTTP 请求并返回 HTTP 响应。DRF 的 View 同样如此,但它提供了更适合处理 API 请求/响应的类。
DRF 提供了多种 View 的实现方式:
APIView
: DRF 提供的基础 View 类,是 DjangoView
类的增强版。它处理 DRF 的Request
和Response
对象,并提供认证、权限、限流等功能。你需要自己实现各种 HTTP 方法(get
,post
,put
,delete
等)。- 通用视图类 (Generic Views): 基于
APIView
,提供了一系列 Mixins (混入类),用于实现常见的操作(如 ListModelMixin, CreateModelMixin, RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin)。你可以组合这些 Mixins 来快速构建 View。 - 视图集 (ViewSets): 更高层次的抽象。ViewSet 不提供像
get
,post
这样的方法,而是提供像list
,create
,retrieve
,update
,partial_update
,destroy
这样的操作。ViewSets 通常与 Router 配合使用,可以自动生成 URL 模式。这使得为一组相关的视图编写代码变得非常高效。
对于常见的 Model CRUD 操作,ModelViewSet
是最常用的选择,因为它集成了所有必要的 Mixins 和 GenericAPIView
的功能。我们将使用 ModelViewSet
来创建 Product
的 API 视图。
打开 products/views.py
文件:
“`python
products/views.py
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
“””
API endpoint that allows products to be viewed or edited.
“””
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
“`
就这么简单!通过继承 ModelViewSet
,我们立即获得了 list
(GET /products/), create
(POST /products/), retrieve
(GET /products/{id}/), update
(PUT /products/{id}/), partial_update
(PATCH /products/{id}/), 和 destroy
(DELETE /products/{id}/) 等一系列完整的 CRUD API 操作。
queryset
: 指定了该视图集将操作的数据集。这里是所有的Product
对象,并按创建时间倒序排列。serializer_class
: 指定了用于序列化和反序列化数据的 Serializer 类。
第四步:配置 URL 路由
Django 的 URLconf 负责将 URL 映射到对应的 View。DRF 为 ViewSet 提供了方便的 Router
类,可以自动为 ViewSet 生成标准的 URL 模式。
打开 myapi_project/urls.py
文件:
“`python
myapi_project/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from products import views
创建一个 Router 实例
router = routers.DefaultRouter()
注册 ProductViewSet 到路由,base_name 通常是 Model 的小写名称
router.register(r’products’, views.ProductViewSet)
urlpatterns = [
path(‘admin/’, admin.site.urls),
# 将 Router 生成的 URL 模式包含进来
path(”, include(router.urls)), # 将 API 根路径设置为 Router 的 URL
# 添加 DRF 提供的登录/登出视图,用于 Browsable API
path(‘api-auth/’, include(‘rest_framework.urls’, namespace=’rest_framework’)),
]
“`
这里:
- 我们从
rest_framework
导入了routers
。 - 创建了一个
DefaultRouter
实例。 - 使用
router.register()
方法注册了ProductViewSet
。第一个参数是 URL 前缀(如'products'
),第二个参数是 ViewSet 类。DRF 会根据 ViewSet 的操作自动生成/products/
(列表/创建) 和/products/{id}/
(详情/更新/删除) 等 URL。 - 在
urlpatterns
中,使用include(router.urls)
将 Router 生成的所有 URL 模式包含进来。我们将其放在根路径'
下,所以产品 API 的入口将是/products/
。 - 添加了
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
。这会为可浏览的 API 添加登录和登出链接,方便你在浏览器中测试需要认证的 API。
运行服务器并测试
现在,我们可以运行开发服务器并测试我们的第一个 DRF API 了。
bash
python manage.py runserver
打开浏览器,访问 http://127.0.0.1:8000/products/
。
你应该能看到 DRF 提供的可浏览的 API 界面!
- 列表页 (
/products/
): 你可以看到所有产品的数据(如果数据库中有的话)。页面下方会有一个表单,允许你发送 POST 请求来创建新的产品。 - 详情页 (
/products/{id}/
): 点击列表中的某个产品,会跳转到其详情页(如/products/1/
)。在这里,你可以看到该产品的详细信息,并可以使用表单发送 PUT、PATCH 或 DELETE 请求来更新或删除该产品。
可浏览的 API 是 DRF 的一个强大特性,它使得 API 的开发、测试和文档化变得非常方便。
你也可以使用其他工具(如 curl
、Postman 或 Insomnia)来测试 API。
例如,使用 curl
创建一个新产品:
bash
curl -X POST http://127.0.0.1:8000/products/ \
-H "Content-Type: application/json" \
-d '{"name": "Laptop", "description": "A powerful laptop", "price": 1200.00, "stock": 50}'
使用 curl
获取产品列表:
bash
curl http://127.0.0.1:8000/products/
使用 curl
获取某个产品详情 (假设ID为1):
bash
curl http://127.0.0.1:8000/products/1/
深入 Serializer:验证和字段控制
ModelSerializer
默认会根据 Model 字段进行基本的验证(如必填、数据类型、最大长度等)。但你也可以自定义验证规则。
自定义字段验证:
你可以在 Serializer 中为特定字段编写 validate_<field_name>
方法。
“`python
products/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ‘all‘
# 验证 stock 字段不能为负数
def validate_stock(self, value):
if value < 0:
raise serializers.ValidationError("库存不能为负数。")
return value
# 验证 price 字段不能为负数
def validate_price(self, value):
if value < 0:
raise serializers.ValidationError("价格不能为负数。")
return value
“`
对象级别验证:
你也可以编写 validate
方法对整个对象的多个字段进行交叉验证。
“`python
products/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ‘all‘
# ... (字段级别验证方法如 validate_stock, validate_price) ...
# 对象级别验证:例如,如果库存为0,描述必须包含“缺货”
def validate(self, data):
# data 是一个字典,包含了经过字段级别验证后的所有数据
stock = data.get('stock', getattr(self.instance, 'stock', None)) # 考虑创建和更新的情况
description = data.get('description', getattr(self.instance, 'description', ''))
if stock == 0 and '缺货' not in description:
raise serializers.ValidationError("库存为0时,描述必须包含 '缺货' 字样。")
return data # 验证成功必须返回 data
“`
手动控制字段:
除了 __all__
和 fields
/ exclude
,你还可以在 Serializer 中显式定义字段,以自定义其行为、表示方式或添加不存在于 Model 中的字段。
“`python
products/serializers.py
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
# 添加一个只读字段,表示产品的状态
status = serializers.SerializerMethodField()
class Meta:
model = Product
fields = ['id', 'name', 'price', 'stock', 'status'] # 确保包含 status 字段
# SerializerMethodField 对应的方法,方法名必须是 get_<field_name>
def get_status(self, obj):
# obj 是当前序列化的 Product 实例
if obj.stock > 10:
return "有库存"
elif obj.stock > 0:
return "库存紧张"
else:
return "缺货"
# ... (验证方法) ...
“`
通过自定义 Serializer 字段和验证逻辑,你可以精确控制 API 的输入和输出格式以及数据有效性。
身份认证 (Authentication)
默认情况下,我们的 API 是公开的,任何人都可以访问和修改数据。在实际应用中,我们需要保护 API,只允许经过认证的用户进行操作。
DRF 提供了多种认证方案,如:
SessionAuthentication
: 基于 Django session 的认证,主要用于可浏览的 API 和与你的 Django 网站共享认证状态的场景。TokenAuthentication
: 基于 token 的认证,客户端在请求头中发送一个 token 进行认证。适合单页应用或移动应用。BasicAuthentication
: 基于 HTTP Basic Authentication,发送用户名和密码。不安全,除非在 HTTPS 环境下使用。RemoteUserAuthentication
: 基于 Web 服务器提供的认证信息。
我们以最常用的 TokenAuthentication
为例。
-
安装
authtoken
应用:
在settings.py
的INSTALLED_APPS
中添加'rest_framework.authtoken'
。“`python
myapi_project/settings.py
INSTALLED_APPS = [
# … other apps
‘rest_framework’,
‘rest_framework.authtoken’, # <– 添加 authtoken 应用
‘products’,
]…
“`
-
运行迁移:
authtoken
应用需要创建数据库表来存储 tokens。bash
python manage.py migrate -
为用户生成 Token:
你可以通过 Django shell 或创建一个专门的 API 接口来为用户生成 token。最简单的方式是使用 Django shell 或 Django Admin。在 shell 中为现有用户生成 token (首先需要创建用户
python manage.py createsuperuser
):“`bash
python manage.py shell在 shell 中输入以下代码
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token获取你想生成token的用户(例如用户名为 ‘admin’)
user = User.objects.get(username=’admin’)
为该用户创建或获取token
token, created = Token.objects.get_or_create(user=user)
print(token.key) # 打印出生成的token
exit()
“` -
应用认证类到 ViewSet:
在products/views.py
的ProductViewSet
中添加authentication_classes
属性。“`python
products/views.py
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication # <– 导入认证类
from .models import Product
from .serializers import ProductSerializerclass ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication] # <– 应用 Token 认证
# permission_classes 将在下一节讲解
“`
现在,当你访问 /products/
或 /products/{id}/
端点时,如果没有在请求头中提供有效的 Token,你将收到 401 Unauthorized
或 403 Forbidden
响应(取决于权限设置)。
客户端如何发送 Token?
客户端需要在 HTTP 请求头中添加 Authorization
字段,格式为 Token <你的Token>
。
例如,使用 curl
:
bash
curl http://127.0.0.1:8000/products/ \
-H "Authorization: Token 你刚刚生成的token"
权限控制 (Permissions)
认证(Authentication)是确定“你是谁”,而权限(Permission)是确定“你被允许做什么”。即使一个用户通过了认证,他/她也可能没有权限执行某个操作(例如,普通用户不能删除产品)。
DRF 提供了多种权限类,如:
AllowAny
: 允许任何人访问(默认)。IsAuthenticated
: 只允许认证用户访问。IsAdminUser
: 只允许管理员用户访问。IsAuthenticatedOrReadOnly
: 允许认证用户进行任何操作,未认证用户只能进行安全的方法(GET, HEAD, OPTIONS)。DjangoModelPermissions
: 标准 Djangodjango.contrib.auth
模型权限。DjangoObjectPermissions
: 基于对象的权限。
你可以将权限类列表添加到 ViewSet 的 permission_classes
属性中。DRF 会按顺序检查这些权限,只要有一个权限通过,请求就被允许。
继续修改 products/views.py
的 ProductViewSet
:
“`python
products/views.py
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated # <– 导入权限类
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated] # <– 只允许认证用户访问
“`
现在,只有携带有效 Token 的认证用户才能访问 Product
API。
更细粒度的权限:
你可能希望普通认证用户可以查看产品列表和详情 (GET),但只有管理员才能创建、更新或删除产品 (POST, PUT, PATCH, DELETE)。可以使用 IsAuthenticatedOrReadOnly
和 IsAdminUser
的组合来实现。
“`python
products/views.py
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
导入多个权限类
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser
from .models import Product
from .serializers import ProductSerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
# 权限类列表。按顺序检查。
# 1. 如果是安全方法 (GET, HEAD, OPTIONS),IsAuthenticatedOrReadOnly 允许访问。
# 2. 如果是非安全方法 (POST, PUT, PATCH, DELETE),IsAuthenticatedOrReadOnly 要求认证。
# 3. 如果认证用户是管理员,IsAdminUser 允许访问。
permission_classes = [IsAuthenticatedOrReadOnly, IsAdminUser]
# 可以为不同的动作定义不同的权限
# def get_permissions(self):
# """
# Instantiates and returns the list of permissions that this view requires.
# """
# if self.action == 'list' or self.action == 'retrieve':
# permission_classes = [AllowAny] # 允许任何人查看列表和详情
# else:
# permission_classes = [IsAdminUser] # 其他操作只允许管理员
# return [permission() for permission in permission_classes]
“`
上面注释掉的 get_permissions
方法展示了如何在 ViewSet 中为不同的操作(如 list
, create
, retrieve
等)应用不同的权限策略。通过覆盖 get_permissions
方法,你可以实现非常灵活的权限控制。
分页 (Pagination)
当数据集很大时,一次性返回所有数据会导致性能问题和带宽浪费。分页是处理大型数据集的常用方式,DRF 提供了内置的分页支持。
DRF 提供了多种分页类:
PageNumberPagination
: 基于页码的分页。LimitOffsetPagination
: 基于偏移量和限制数量的分页(类似 SQL 的 LIMIT 和 OFFSET)。CursorPagination
: 基于游标的分页,适合大型数据集且需要稳定的分页结果(避免新增或删除数据影响分页)。
我们可以通过在 settings.py
中设置全局默认分页,或者在 View/ViewSet 中单独设置。
全局设置分页 (PageNumberPagination 为例):
“`python
myapi_project/settings.py
… other settings
REST_FRAMEWORK = {
‘DEFAULT_AUTHENTICATION_CLASSES’: [
‘rest_framework.authentication.TokenAuthentication’,
‘rest_framework.authentication.SessionAuthentication’, # 用于 Browsable API 登录
],
‘DEFAULT_PERMISSION_CLASSES’: [
‘rest_framework.permissions.IsAuthenticated’, # 默认所有 API 需要认证
],
‘DEFAULT_PAGINATION_CLASS’: ‘rest_framework.pagination.PageNumberPagination’, # <– 设置默认分页类
‘PAGE_SIZE’: 10 # <– 每页显示的条目数
}
… other settings
“`
在 settings.py
中配置后,所有没有单独设置分页的 ViewSet 都会应用这个默认分页。访问 /products/
将会看到分页结果,可以通过查询参数 ?page=2
或 ?page_size=20
(如果允许) 来控制分页。
在 ViewSet 中单独设置分页:
你也可以在 ProductViewSet
中覆盖全局设置或为没有全局设置的 ViewSet 添加分页。
“`python
products/views.py
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination # <– 导入分页类
from .models import Product
from .serializers import ProductSerializer
class ProductPagination(PageNumberPagination): # 可以自定义分页类
page_size = 5 # 每页5条
page_size_query_param = ‘page_size’ # 允许客户端通过 ?page_size= 来控制每页大小
max_page_size = 100 # 最大允许每页显示100条
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
pagination_class = ProductPagination # <– 应用自定义分页类
“`
现在,Product
API 将使用 ProductPagination
中定义的规则进行分页。
过滤和搜索 (Filtering & Searching)
除了分页,过滤和搜索也是 API 中常用的功能。DRF 提供了灵活的方式来实现这些功能,通常借助于第三方库 django-filter
。
-
安装
django-filter
:bash
pip install django-filter -
注册应用:
在settings.py
的INSTALLED_APPS
中添加'django_filter'
。“`python
myapi_project/settings.py
INSTALLED_APPS = [
# … other apps
‘rest_framework’,
‘rest_framework.authtoken’,
‘products’,
‘django_filter’, # <– 添加 django_filter
]…
“`
-
配置 DRF 使用
django-filter
:
在settings.py
的REST_FRAMEWORK
中添加DEFAULT_FILTER_BACKENDS
。“`python
myapi_project/settings.py
REST_FRAMEWORK = {
# … other settings like authentication, permissions, pagination
‘DEFAULT_FILTER_BACKENDS’: [
‘django_filters.rest_framework.DjangoFilterBackend’ # <– 添加过滤后端
],
# ‘DEFAULT_SEARCH_BACKENDS’: [ … ], # 如果需要搜索功能,也可以在这里配置
}
“` -
在 ViewSet 中指定可过滤字段:
在ProductViewSet
中添加filter_backends
和filterset_fields
属性。“`python
products/views.py
from rest_framework import viewsets
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated
from rest_framework.pagination import PageNumberPagination
from django_filters.rest_framework import DjangoFilterBackend # <– 导入过滤后端from .models import Product
from .serializers import ProductSerializer(可选) 自定义分页类 ProductPagination
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all().order_by(‘-created_at’)
serializer_class = ProductSerializer
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
# pagination_class = ProductPagination # (可选) 应用自定义分页类# 添加过滤后端 filter_backends = [DjangoFilterBackend] # 指定允许通过 URL 查询参数进行过滤的字段 filterset_fields = ['name', 'price', 'stock'] # 例如,访问 /products/?stock=0 将只返回库存为0的产品 # 访问 /products/?price__gte=1000 将只返回价格大于等于1000的产品 (使用 __gte 进行范围过滤) # 如果需要简单的搜索功能 (通过一个查询参数搜索多个字段) # from rest_framework import filters # 导入搜索后端 # filter_backends = [DjangoFilterBackend, filters.SearchFilter] # 添加搜索后端 # search_fields = ['name', 'description'] # 指定可以搜索的字段 # 例如,访问 /products/?search=laptop 将在 name 和 description 字段中搜索 'laptop' # 如果需要排序功能 # from rest_framework import filters # 导入排序后端 # filter_backends = [DjangoFilterBackend, filters.OrderingFilter] # 添加排序后端 # ordering_fields = ['name', 'price', 'stock'] # 指定可以排序的字段 # ordering = ['price'] # 默认按价格升序排序 # 例如,访问 /products/?ordering=-price 将按价格降序排序
“`
现在,你的 Product
API 就支持通过 URL 查询参数进行过滤了,例如 /products/?stock=0
。通过结合 DjangoFilterBackend
、filters.SearchFilter
和 filters.OrderingFilter
,你可以轻松实现强大的数据查询功能。
可浏览的 API 和渲染器 (Renderers)
我们之前已经体验了可浏览的 API。它是 DRF 的一个默认渲染器 (BrowsableAPIRenderer
) 的输出。除了 HTML 格式的可浏览 API,DRF 还支持多种渲染器,用于将序列化后的数据转换为不同的格式。
默认情况下,DRF 配置了 JSONRenderer
和 BrowsableAPIRenderer
。当客户端发送请求时,DRF 会根据请求的 Accept
头来选择合适的渲染器。如果 Accept
头是 application/json
,就使用 JSONRenderer
返回 JSON 数据;如果 Accept
头是 text/html
并且是来自浏览器的请求,就可能使用 BrowsableAPIRenderer
返回 HTML 页面。
你可以在 settings.py
中配置默认的渲染器:
“`python
myapi_project/settings.py
REST_FRAMEWORK = {
# … other settings
‘DEFAULT_RENDERER_CLASSES’: [
‘rest_framework.renderers.JSONRenderer’,
‘rest_framework.renderers.BrowsableAPIRenderer’,
],
}
“`
你也可以在 View 或 ViewSet 中覆盖它:
“`python
products/views.py
from rest_framework import viewsets
… other imports
from rest_framework.renderers import JSONRenderer # 导入 JSON 渲染器
from rest_framework.renderers import BrowsableAPIRenderer # 导入 Browsable API 渲染器
class ProductViewSet(viewsets.ModelViewSet):
# … other properties
renderer_classes = [JSONRenderer, BrowsableAPIRenderer] # 明确指定渲染器
“`
这通常在你需要支持除 JSON 和可浏览 API 之外的其他格式时才会修改,例如 XML 或 YAML。
总结和下一步
恭喜你!你已经成功迈入了 Django REST Framework 的大门,并学会了构建一个基础的、具备 CRUD 功能、认证、权限、分页和过滤的 API。
我们回顾一下学到的核心概念:
- Serializers: 处理数据序列化和反序列化,包括数据验证。
ModelSerializer
是最便捷的方式。 - Views: 处理请求和响应。
ModelViewSet
是实现 Model CRUD 操作的高效工具,常与 Router 配合使用。 - URLs: 通过
DefaultRouter
可以方便地为 ViewSet 生成 URL 模式。 - Authentication: 验证请求发送者的身份。
TokenAuthentication
是常见的 API 认证方式。 - Permissions: 控制认证用户被允许执行哪些操作。
IsAuthenticated
,IsAdminUser
,IsAuthenticatedOrReadOnly
是常用的权限类。 - Pagination: 分页处理大型数据集,提高性能。
- Filtering & Searching: 通过查询参数过滤和搜索数据,通常使用
django-filter
。 - Browsable API: 友好的网页界面,方便测试和调试 API。
接下来,你可以继续深入学习:
- 自定义 Serializer: 学习如何处理嵌套关系、自定义字段和验证逻辑。
- 自定义 ViewSet actions: 在
ModelViewSet
中添加额外的非 CRUD 操作。 - 基于函数的 API 视图 (@api_view): 对于非常简单的场景或不需要 Model 的 API,可以使用函数视图。
- 测试 API: 学习如何使用 Django 的测试框架或 DRF 的测试客户端来测试你的 API 端点。
- 限流 (Throttling): 限制客户端的请求频率,防止滥用。
- 版本控制 (Versioning): 如何管理 API 的不同版本。
- 文档生成: 使用第三方库(如
drf-yasg
或drf-spectacular
)为 API 生成 Swagger/OpenAPI 文档。 - 部署 API: 学习如何将你的 Django/DRF 项目部署到生产环境。
Django REST Framework 是一个功能强大的框架,掌握了其核心概念后,你将能够高效地构建各种复杂的 Web API 来支持你的 Web 应用、移动应用或其他服务。不断实践和探索文档是提升技能的最佳途径。
祝你在 API 开发的旅程中一切顺利!