Django REST框架学习指南

一、今日学习内容概览

知识模块 重点内容
序列化(Serialization) 模型序列化、验证器、嵌套序列化
视图集(ViewSets) 模型视图集、只读视图集、CRUD操作
路由(Routing) 自动URL路由、自定义路由、嵌套路由

二、详细内容讲解

1. 序列化(Serialization)

序列化是REST框架最核心的概念之一,它负责将复杂的数据类型(如Django模型实例)转换为Python原生数据类型,以便轻松渲染成JSON、XML等格式。

让我们通过一个实际的例子来理解序列化:

# models.py
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
    publication_date = models.DateField()
    isbn = models.CharField(max_length=13)
    price = models.DecimalField(max_digits=6, decimal_places=2)

    def __str__(self):
        return self.title

现在,让我们为这些模型创建序列化器:

# serializers.py
from rest_framework import serializers
from .models import Author, Book

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'created_at']
        read_only_fields = ['created_at']
        
    def validate_email(self, value):
        """
        自定义邮箱验证
        """
        if not value.endswith('@example.com'):
            raise serializers.ValidationError("邮箱域名必须是example.com")
        return value

class BookSerializer(serializers.ModelSerializer):
    author_name = serializers.CharField(source='author.name', read_only=True)
    
    class Meta:
        model = Book
        fields = ['id', 'title', 'author', 'author_name', 'publication_date', 
                 'isbn', 'price']
        
    def validate_isbn(self, value):
        """
        ISBN验证
        """
        if len(value) != 13:
            raise serializers.ValidationError("ISBN必须是13位")
        return value

2. 视图集(ViewSets)

视图集提供了一种将常见的视图逻辑组合在一起的方式。下面是一个完整的视图集示例:

# views.py
from rest_framework import viewsets, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Author, Book
from .serializers import AuthorSerializer, BookSerializer

class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer
    filter_backends = [filters.SearchFilter]
    search_fields = ['name', 'email']
    
    @action(detail=True, methods=['get'])
    def books(self, request, pk=None):
        """
        获取作者的所有图书
        """
        author = self.get_object()
        books = author.books.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data)

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['title', 'isbn']
    ordering_fields = ['publication_date', 'price']
    
    def perform_create(self, serializer):
        """
        创建图书时的自定义行为
        """
        serializer.save()

3. 路由(Routing)

DRF提供了便捷的路由注册方式:

# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import AuthorViewSet, BookViewSet

router = DefaultRouter()
router.register(r'authors', AuthorViewSet)
router.register(r'books', BookViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

三、实战示例:图书管理系统API

让我们创建一个完整的示例,展示如何将上述所有概念结合起来:
在这里插入图片描述

4. 完整的API实现示例

下面是一个完整的实现,包含了高级功能:

# permissions.py
from rest_framework import permissions

class IsAdminOrReadOnly(permissions.BasePermission):
    """
    自定义权限:仅管理员可以修改
    """
    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True
        return request.user and request.user.is_staff

# serializers.py
class AuthorDetailSerializer(serializers.ModelSerializer):
    books = BookSerializer(many=True, read_only=True)
    
    class Meta:
        model = Author
        fields = ['id', 'name', 'email', 'created_at', 'books']

# views.py
from rest_framework.pagination import PageNumberPagination
from rest_framework.filters import SearchFilter, OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend

class CustomPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'page_size'
    max_page_size = 100

class AuthorViewSet(viewsets.ModelViewSet):
    queryset = Author.objects.all()
    serializer_class = AuthorSerializer
    pagination_class = CustomPagination
    permission_classes = [IsAdminOrReadOnly]
    filter_backends = [DjangoFilterBackend, SearchFilter, OrderingFilter]
    filterset_fields = ['created_at']
    search_fields = ['name', 'email']
    ordering_fields = ['name', 'created_at']
    
    def get_serializer_class(self):
        if self.action == 'retrieve':
            return AuthorDetailSerializer
        return AuthorSerializer
    
    @action(detail=True, methods=['post'])
    def add_book(self, request, pk=None):
        author = self.get_object()
        serializer = BookSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(author=author)
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

5. API测试

为了确保API的可靠性,我们需要编写测试:

# tests.py
from django.test import TestCase
from rest_framework.test import APIClient
from rest_framework import status
from django.urls import reverse
from .models import Author, Book

class AuthorAPITest(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.author_data = {
            'name': 'John Doe',
            'email': 'john@example.com'
        }
        self.author = Author.objects.create(**self.author_data)
        
    def test_get_authors(self):
        response = self.client.get(reverse('author-list'))
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['results']), 1)
        
    def test_create_author(self):
        new_author_data = {
            'name': 'Jane Doe',
            'email': 'jane@example.com'
        }
        response = self.client.post(
            reverse('author-list'),
            new_author_data,
            format='json'
        )
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Author.objects.count(), 2)

四、最佳实践和注意事项

  1. 序列化器最佳实践:

    • 总是定义Meta.fields而不是使用__all__
    • 对敏感字段使用read_only_fields
    • 使用嵌套序列化时注意性能影响
  2. 视图集最佳实践:

    • 使用适当的权限类
    • 实现过滤和分页
    • 合理使用@action装饰器定义额外动作
  3. 路由最佳实践:

    • 使用有意义的URL前缀
    • 适当使用API版本控制
    • 考虑URL命名空间

五、练习任务

  1. 实现一个带有以下功能的图书评论系统:

    • 评论的CRUD操作
    • 评分功能
    • 评论嵌套展示
  2. 为图书管理系统添加以下功能:

    • 图书分类功能
    • 作者详情页面
    • 高级搜索功能

六、性能优化建议

  1. 使用select_related()prefetch_related()优化查询:
class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.select_related('author')
    # ...
  1. 使用缓存改善性能:
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

class AuthorViewSet(viewsets.ModelViewSet):
    @method_decorator(cache_page(60 * 15))  # 缓存15分钟
    def list(self, request, *args, **kwargs):
        return super().list(request, *args, **kwargs)
  1. 使用适当的分页机制:
from rest_framework.pagination import CursorPagination

class CustomCursorPagination(CursorPagination):
    page_size = 30
    ordering = '-created_at'

七、调试技巧

  1. 使用DRF的内置调试工具:

    • Browsable API
    • coreapi文档生成
    • Django Debug Toolbar
  2. 日志配置:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'file': {
            'level': 'DEBUG',
            'class': 'logging.FileHandler',
            'filename': 'debug.log',
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['file'],
            'level': 'DEBUG',
            'propagate': True,
        },
    },
}

八、总结

今天我们学习了Django REST框架的三个核心概念:序列化、视图集和路由。通过实际的图书管理系统示例,我们看到了如何将这些概念结合起来构建一个完整的REST API。记住以下关键点:

  1. 序列化器负责数据转换和验证
  2. 视图集提供了标准的CRUD操作
  3. 路由系统自动生成URL模式

怎么样今天的内容还满意吗?再次感谢朋友们的观看,关注GZH:凡人的AI工具箱,回复666,送您价值199的AI大礼包。最后,祝您早日实现财务自由,还请给个赞,谢谢!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐