Python Django REST Framework实战:构建RESTful API

引言

在Python Web开发中,Django REST Framework(DRF)是构建RESTful API的首选框架。作为一名从Rust转向Python的后端开发者,我深刻体会到DRF在快速构建高质量API方面的优势。DRF提供了强大的序列化器、视图和认证系统,使得API开发变得更加高效。

DRF核心概念

什么是Django REST Framework

Django REST Framework是基于Django的RESTful API框架,具有以下特点:

  • 序列化器:将模型数据转换为JSON格式
  • 视图集:提供CRUD操作的统一接口
  • 认证系统:支持多种认证方式
  • 权限控制:细粒度的权限管理
  • 分页支持:内置分页功能

架构设计

┌─────────────────────────────────────────────────────────────┐
│                   DRF 架构层次                             │
│  ┌──────────────┐    ┌──────────────┐    ┌──────────────┐ │
│  │   路由层     │───▶│   视图层     │───▶│   序列化层   │ │
│  │ (URL Router) │    │ (ViewSet)    │    │ (Serializer) │ │
│  └──────────────┘    └──────────────┘    └──────────────┘ │
│                                                  │        │
│                                                  ▼        │
│  ┌──────────────────────────────────────────────────────┐  │
│  │                    数据层 (Model)                    │  │
│  └──────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────┘

环境搭建与基础配置

安装依赖

pip install django djangorestframework

项目配置

# settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'myapp',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
}

序列化器实战

基本序列化器

from rest_framework import serializers
from .models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'is_active']

class UserCreateSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)
    
    class Meta:
        model = User
        fields = ['username', 'email', 'password']
    
    def create(self, validated_data):
        user = User.objects.create_user(
            username=validated_data['username'],
            email=validated_data['email'],
            password=validated_data['password']
        )
        return user

嵌套序列化器

from rest_framework import serializers
from .models import Post, Comment

class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ['id', 'content', 'created_at']

class PostSerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True, read_only=True)
    author_name = serializers.CharField(source='author.username', read_only=True)
    
    class Meta:
        model = Post
        fields = ['id', 'title', 'content', 'author_name', 'comments', 'created_at']

视图集实战

基本视图集

from rest_framework import viewsets
from .models import User
from .serializers import UserSerializer

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    
    def get_queryset(self):
        queryset = super().get_queryset()
        username = self.request.query_params.get('username')
        if username:
            queryset = queryset.filter(username__icontains=username)
        return queryset

自定义视图集

from rest_framework import viewsets, status
from rest_framework.response import Response
from .models import Post
from .serializers import PostSerializer

class PostViewSet(viewsets.ViewSet):
    def list(self, request):
        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data)
    
    def retrieve(self, request, pk=None):
        post = Post.objects.get(pk=pk)
        serializer = PostSerializer(post)
        return Response(serializer.data)
    
    def create(self, request):
        serializer = PostSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save(author=request.user)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

路由配置

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import UserViewSet, PostViewSet

router = DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'posts', PostViewSet)

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

认证与权限

Token认证

# settings.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
    ],
}

# urls.py
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
    path('api-token-auth/', obtain_auth_token),
]

自定义权限

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

实际业务场景

场景一:博客API

from rest_framework import viewsets, permissions
from .models import Post, Comment
from .serializers import PostSerializer, CommentSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
    
    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer
    
    def get_queryset(self):
        post_id = self.request.query_params.get('post_id')
        if post_id:
            return self.queryset.filter(post_id=post_id)
        return self.queryset

场景二:分页配置

from rest_framework.pagination import PageNumberPagination

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

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    pagination_class = CustomPagination

性能优化

查询优化

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.select_related('author').prefetch_related('comments').all()
    serializer_class = PostSerializer

缓存

from django.core.cache import cache
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def get_stats(request):
    cache_key = 'api_stats'
    stats = cache.get(cache_key)
    
    if not stats:
        stats = calculate_stats()
        cache.set(cache_key, stats, 60 * 5)
    
    return Response(stats)

总结

Django REST Framework为Python后端开发者提供了强大的API开发能力。通过序列化器、视图集和认证系统,可以快速构建高质量的RESTful API。从Rust开发者的角度来看,DRF的声明式API设计与Rust的类型安全理念有相似之处。

在实际项目中,建议合理使用视图集和序列化器来提高开发效率,并注意查询优化和缓存来提升性能。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐