Django REST Framework (DRF) 是一个强大且灵活的工具包,用于构建 Web APIs。它基于 Django 框架,提供了处理复杂 API 的功能,同时保持了易用性和可扩展性。
首先,在你的 Django 项目中安装 DRF:
bashpip install djangorestframework
然后在项目的 settings.py
文件中的 INSTALLED_APPS
列表里添加 'rest_framework'
:
pythonINSTALLED_APPS = [
...
'rest_framework',
]
序列化器负责将复杂的 Django 模型实例或查询集转换为 Python 数据类型(如字典),然后可以轻松地渲染成 JSON 或其他格式。
假设我们有一个简单的模型 Book
:
python# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
接下来,创建一个序列化器来处理这个模型:
python# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__' # 或者指定字段 ['title', 'author']
视图定义了如何处理来自客户端的请求。你可以使用基于函数的视图或基于类的视图。这里以基于类的视图为例:
python# views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
为了让应用程序能够响应 HTTP 请求,需要配置 URL 路由。对于视图集,可以使用 DefaultRouter
自动为你生成路由:
python# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
router.register(r'books', BookViewSet)
urlpatterns = [
path('', include(router.urls)),
]
为了保护你的 API,可以设置权限和认证。例如,只允许已认证的用户访问 API:
python# views.py
from rest_framework.permissions import IsAuthenticated
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [IsAuthenticated] # 设置权限
你也可以在 settings.py
中全局设置默认的认证和权限策略:
pythonREST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.BasicAuthentication',
],
}
当你处理大量数据时,分页是非常有用的。DRF 提供了开箱即用的支持:
在 settings.py
中配置全局分页策略:
pythonREST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 10
}
或者,在特定的视图或视图集中局部配置:
pythonfrom rest_framework.pagination import PageNumberPagination
class LargeResultsSetPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = LargeResultsSetPagination
完成上述步骤后,你可以启动 Django 开发服务器并测试你的 API:
bashpython manage.py runserver
打开浏览器访问 http://127.0.0.1:8000/books/
查看所有书籍列表,或者使用 Postman 等工具进行更详细的测试。
在处理大量数据时,提供过滤功能是非常有用的。DRF 提供了多种方法来实现过滤,包括基于查询参数的简单过滤和更复杂的搜索。
django-filter
首先安装 django-filter
:
bashpip install django-filter
然后,在 settings.py
中添加 'django_filters'
到 INSTALLED_APPS
:
pythonINSTALLED_APPS = [
...
'django_filters',
]
接着,配置 DRF 使用 DjangoFilterBackend
:
python# settings.py
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
最后,在视图集中指定过滤字段:
python# views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['title', 'author'] # 可以根据需要添加更多字段
或者,你可以定义一个自定义的过滤类:
python# filters.py
import django_filters
from .models import Book
class BookFilter(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')
class Meta:
model = Book
fields = ['title', 'author', 'min_price', 'max_price']
# views.py
from .filters import BookFilter
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = BookFilter
除了过滤,你还可以实现搜索和排序功能。
python# settings.py 或 views.py
from rest_framework.filters import SearchFilter
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [SearchFilter]
search_fields = ['title', 'author']
pythonfrom rest_framework.filters import OrderingFilter
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['published_date', 'title']
ordering = ['published_date'] # 默认排序
有时你需要对默认的行为进行自定义,例如覆盖某些方法或添加额外的功能。
get_queryset
方法pythonclass BookViewSet(viewsets.ModelViewSet):
serializer_class = BookSerializer
def get_queryset(self):
user = self.request.user
return Book.objects.filter(owner=user)
pythonfrom rest_framework.decorators import action
from rest_framework.response import Response
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
@action(detail=True, methods=['post'])
def highlight(self, request, pk=None):
book = self.get_object()
return Response(book.highlighted)
DRF 支持多种版本控制策略,如 URL 路径、请求头等。
python# urls.py
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'books', BookViewSet, basename='book')
urlpatterns = router.urls
# settings.py
REST_FRAMEWORK = {
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
'DEFAULT_VERSION': 'v1',
'ALLOWED_VERSIONS': ['v1', 'v2'],
}
然后,你的 API URL 可能会变成 /api/v1/books/
和 /api/v2/books/
。
文档对于 API 来说非常重要。DRF 提供了几种方式来生成 API 文档。
drf-yasg
首先安装 drf-yasg
:
bashpip install -U drf-yasg
然后在 settings.py
中添加到 INSTALLED_APPS
:
pythonINSTALLED_APPS = [
...
'drf_yasg',
]
配置 URL:
python# urls.py
from django.urls import path, re_path
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Book API",
default_version='v1',
description="Test description",
terms_of_service="https://www.google.com/policies/terms/",
contact=openapi.Contact(email="contact@yourapi.local"),
license=openapi.License(name="BSD License"),
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [
re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
re_path(r'^redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]
现在,你可以通过访问 /swagger/
或 /redoc/
查看 API 文档。
编写单元测试是确保 API 正确性和稳定性的重要步骤。DRF 提供了一些工具来帮助你测试 API。
python# tests.py
from django.test import TestCase
from rest_framework.test import APIClient
from rest_framework import status
from .models import Book
class BookAPITestCase(TestCase):
def setUp(self):
self.client = APIClient()
self.book_data = {'title': 'Test Book', 'author': 'Author Name', 'published_date': '2023-04-10'}
self.response = self.client.post('/books/', self.book_data, format="json")
def test_api_can_create_book(self):
self.assertEqual(self.response.status_code, status.HTTP_201_CREATED)
def test_api_can_get_books(self):
books = Book.objects.all()
response = self.client.get('/books/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertContains(response, books[0].title)
以上内容涵盖了从基础到中级的多个方面,包括过滤、搜索、排序、自定义行为、版本控制、文档化以及测试。