Django REST Framework 实战:构建 RESTful API

Django REST Framework(简称DRF)是一个强大而灵活的工具,用于构建 Web API。它是Django生态中最流行的REST API框架,被广泛用于前后端分离项目、移动端后端、微服务架构等场景。本文将从零开始,带你掌握DRF的核心用法。

一、环境准备

1. 安装依赖

pip install django djangorestframework

2. 创建项目

django-admin startproject myapi
cd myapi
python manage.py startapp blog

3. 配置settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'blog',
]

二、定义模型

在 blog/models.py 中创建文章模型:

from django.db import models

class Article(models.Model):
    title = models.CharField('标题', max_length=200)
    content = models.TextField('内容')
    author = models.CharField('作者', max_length=100)
    created_at = models.DateTimeField('创建时间', auto_now_add=True)
    updated_at = models.DateTimeField('更新时间', auto_now=True)
    is_published = models.BooleanField('是否发布', default=False)

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章'
        ordering = ['-created_at']

    def __str__(self):
        return self.title

执行迁移:

python manage.py makemigrations
python manage.py migrate

三、序列化器(Serializer)

序列化器是DRF的核心概念之一,负责将模型实例转换为JSON数据。

在 blog/serializers.py 中创建:

from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author', 'created_at', 'updated_at', 'is_published']
        read_only_fields = ['created_at', 'updated_at']

四、视图(View)

方式一:函数视图

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Article
from .serializers import ArticleSerializer

@api_view(['GET', 'POST'])
def article_list(request):
    if request.method == 'GET':
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)
    elif request.method == 'POST':
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def article_detail(request, pk):
    try:
        article = Article.objects.get(pk=pk)
    except Article.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)
    if request.method == 'GET':
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    elif request.method == 'PUT':
        serializer = ArticleSerializer(article, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

方式二:类视图(推荐)

from rest_framework import generics
from .models import Article
from .serializers import ArticleSerializer

class ArticleListCreate(generics.ListCreateAPIView):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

class ArticleDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

方式三:ViewSet(最推荐)

from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer

    def get_queryset(self):
        queryset = Article.objects.all()
        author = self.request.query_params.get('author')
        if author:
            queryset = queryset.filter(author=author)
        return queryset

五、路由配置

在项目 urls.py 中配置:

from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from blog.views import ArticleViewSet

router = DefaultRouter()
router.register(r'articles', ArticleViewSet)

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

六、API接口一览

配置完成后,DRF自动生成以下接口:

  • GET /api/articles/ 获取文章列表
  • POST /api/articles/ 创建新文章
  • GET /api/articles/{id}/ 获取文章详情
  • PUT /api/articles/{id}/ 更新文章
  • PATCH /api/articles/{id}/ 部分更新文章
  • DELETE /api/articles/{id}/ 删除文章

七、认证与权限

1. 添加认证

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

2. 自定义权限

from rest_framework import permissions

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

八、分页与过滤

1. 分页配置

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}

2. 过滤

安装django-filter:

pip install django-filter
REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
}

九、测试API

使用curl测试:

# 获取文章列表
curl http://localhost:8000/api/articles/

# 创建新文章
curl -X POST http://localhost:8000/api/articles/ -H 'Content-Type: application/json' -d '{"title": "测试文章", "content": "这是内容", "author": "张三"}'

# 更新文章
curl -X PUT http://localhost:8000/api/articles/1/ -H 'Content-Type: application/json' -d '{"title": "更新后的标题", "content": "更新后的内容", "author": "张三"}'

# 删除文章
curl -X DELETE http://localhost:8000/api/articles/1/

十、总结

本文介绍了Django REST Framework的核心用法:

  1. 序列化器:负责数据的序列化和反序列化
  2. 视图:处理HTTP请求,推荐使用ViewSet
  3. 路由:使用DefaultRouter自动生成路由
  4. 认证权限:保护API接口安全
  5. 分页过滤:提升API的可用性

DRF的生态系统非常丰富,还有更多高级功能如JWT认证(djangorestframework-simplejwt)、API文档自动生成(drf-spectacular)等。

希望这篇实战教程对你有帮助!