Django REST Framework 第一个API #

一、项目准备 #

1.1 创建项目和应用 #

bash
# 创建项目
django-admin startproject myapi
cd myapi

# 创建应用
python manage.py startapp articles

1.2 注册应用 #

编辑 myapi/settings.py

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

二、创建模型 #

2.1 定义Article模型 #

编辑 articles/models.py

python
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

2.2 执行数据库迁移 #

bash
python manage.py makemigrations
python manage.py migrate

三、创建序列化器 #

3.1 什么是序列化器 #

序列化器负责将模型实例转换为JSON格式,以及将JSON数据验证并转换为模型实例。

text
┌─────────────────┐         ┌─────────────────┐
│   模型实例      │────────▶│   JSON数据      │
│ (Python对象)    │◀────────│  (API响应)      │
└─────────────────┘  序列化  └─────────────────┘

3.2 创建序列化器 #

创建 articles/serializers.py

python
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 = ['id', 'created_at', 'updated_at']

3.3 序列化器的作用 #

功能 说明
序列化 将模型实例转换为JSON
反序列化 将JSON转换为模型实例
数据验证 验证输入数据的合法性
字段控制 控制哪些字段可以被访问

四、创建视图 #

4.1 方式一:函数视图 #

编辑 articles/views.py

python
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)

4.2 方式二:类视图 #

python
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Article
from .serializers import ArticleSerializer

class ArticleList(APIView):
    def get(self, request):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    def post(self, request):
        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)


class ArticleDetail(APIView):
    def get_object(self, pk):
        try:
            return Article.objects.get(pk=pk)
        except Article.DoesNotExist:
            return None

    def get(self, request, pk):
        article = self.get_object(pk)
        if article is None:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    def put(self, request, pk):
        article = self.get_object(pk)
        if article is None:
            return Response(status=status.HTTP_404_NOT_FOUND)
        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)

    def delete(self, request, pk):
        article = self.get_object(pk)
        if article is None:
            return Response(status=status.HTTP_404_NOT_FOUND)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

4.3 方式三:通用视图(推荐) #

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

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


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

4.4 方式四:视图集(最简洁) #

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

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

五、配置URL #

5.1 配置应用URL #

创建 articles/urls.py

函数视图URL:

python
from django.urls import path
from . import views

urlpatterns = [
    path('articles/', views.article_list, name='article-list'),
    path('articles/<int:pk>/', views.article_detail, name='article-detail'),
]

类视图URL:

python
from django.urls import path
from .views import ArticleList, ArticleDetail

urlpatterns = [
    path('articles/', ArticleList.as_view(), name='article-list'),
    path('articles/<int:pk>/', ArticleDetail.as_view(), name='article-detail'),
]

视图集URL(使用路由器):

python
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

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

urlpatterns = router.urls

5.2 配置项目URL #

编辑 myapi/urls.py

python
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api-auth/', include('rest_framework.urls')),
    path('api/', include('articles.urls')),
]

六、注册Admin #

编辑 articles/admin.py

python
from django.contrib import admin
from .models import Article

@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
    list_display = ['id', 'title', 'author', 'created_at', 'is_published']
    list_filter = ['is_published', 'created_at']
    search_fields = ['title', 'content', 'author']
    ordering = ['-created_at']

七、测试API #

7.1 启动服务器 #

bash
python manage.py runserver

7.2 使用浏览器测试 #

访问 http://127.0.0.1:8000/api/articles/,你将看到DRF的可视化API界面:

text
HTTP 200 OK
Allow: GET, POST, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

[]

7.3 创建文章 #

在浏览器界面中填写表单,或使用curl:

bash
curl -X POST http://127.0.0.1:8000/api/articles/ \
  -H "Content-Type: application/json" \
  -d '{
    "title": "我的第一篇文章",
    "content": "这是文章内容",
    "author": "张三"
  }'

响应:

json
{
    "id": 1,
    "title": "我的第一篇文章",
    "content": "这是文章内容",
    "author": "张三",
    "created_at": "2024-01-15T10:30:00Z",
    "updated_at": "2024-01-15T10:30:00Z",
    "is_published": false
}

7.4 获取文章列表 #

bash
curl http://127.0.0.1:8000/api/articles/

7.5 获取单篇文章 #

bash
curl http://127.0.0.1:8000/api/articles/1/

7.6 更新文章 #

bash
curl -X PUT http://127.0.0.1:8000/api/articles/1/ \
  -H "Content-Type: application/json" \
  -d '{
    "title": "更新后的标题",
    "content": "更新后的内容",
    "author": "张三",
    "is_published": true
  }'

7.7 删除文章 #

bash
curl -X DELETE http://127.0.0.1:8000/api/articles/1/

八、HTTP方法映射 #

HTTP方法 URL 操作 说明
GET /api/articles/ list 获取文章列表
POST /api/articles/ create 创建新文章
GET /api/articles/{id}/ retrieve 获取单篇文章
PUT /api/articles/{id}/ update 完整更新文章
PATCH /api/articles/{id}/ partial_update 部分更新文章
DELETE /api/articles/{id}/ destroy 删除文章

九、视图方式对比 #

方式 代码量 灵活性 适用场景
函数视图 需要精细控制的场景
类视图 需要代码复用的场景
通用视图 标准CRUD操作
视图集 最少 快速开发标准API

十、完整项目结构 #

text
myapi/
├── manage.py
├── myapi/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   ├── asgi.py
│   └── wsgi.py
└── articles/
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations/
    │   └── __init__.py
    ├── models.py
    ├── serializers.py
    ├── tests.py
    ├── urls.py
    └── views.py

十一、总结 #

本章我们创建了第一个DRF API,学习了:

  • 模型定义:使用Django ORM定义数据模型
  • 序列化器:实现数据的序列化和反序列化
  • 视图:多种方式实现API视图
  • URL配置:将视图映射到URL

现在你已经掌握了创建基本API的方法,让我们继续深入学习序列化器的更多功能!

最后更新:2026-03-28