使用DjangoRESTFramework开发RESTfulAPI:完整教程

使用 Django REST Framework 开发 RESTful API:完整教程

Django REST Framework (DRF) 是一个强大且灵活的工具包,用于构建 Web API。它构建在 Django 之上,提供了一套简化的工具和功能,可以让你快速、高效地创建符合 REST 架构风格的 API。本教程将带你逐步了解如何使用 DRF 开发 RESTful API,从安装配置到高级特性,涵盖了构建强大 API 所需的一切。

1. 准备工作:安装与配置

  • 安装 Django 和 DRF:

    bash
    pip install django djangorestframework
    pip install markdown # 用于支持API文档的可浏览性
    pip install django-filter # 用于支持过滤

  • 创建 Django 项目和应用:

    bash
    django-admin startproject myproject
    cd myproject
    python manage.py startapp myapp

  • 配置 settings.py:

    myproject/settings.py 中,将 'rest_framework' 添加到 INSTALLED_APPS

    python
    INSTALLED_APPS = [
    # ... 其他已安装的应用 ...
    'rest_framework',
    'myapp', # 你的应用
    ]

    你还可以在 settings.py 中进行全局的 DRF 配置(可选):
    python
    REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
    'rest_framework.permissions.IsAuthenticated', # 默认需要认证
    ],
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', #分页
    'PAGE_SIZE': 10 #分页数量
    }

2. 定义模型 (Models)

myapp/models.py 中定义你的数据模型。例如,一个简单的 Book 模型:

```python
from django.db import models

class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
publication_date = models.DateField()
isbn = models.CharField(max_length=20, unique=True)

def __str__(self):
    return self.title

```

运行数据库迁移:

bash
python manage.py makemigrations
python manage.py migrate

3. 创建序列化器 (Serializers)

序列化器负责将模型实例(Python 对象)转换为 JSON 等数据格式,反之亦然。 在 myapp/serializers.py 中创建序列化器:

```python
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = 'all' # 或者指定具体的字段:['id', 'title', 'author', ...]
# fields = ['id', 'title', 'author', 'publication_date', 'isbn']
```

4. 构建视图 (Views)

DRF 提供了多种视图类,从简单的 APIView 到高度抽象的 GenericViewSet,可以满足不同复杂度的需求。

  • 使用 APIView (最基础):

    ```python
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status
    from .models import Book
    from .serializers import BookSerializer

    class BookList(APIView):
    def get(self, request):
    books = Book.objects.all()
    serializer = BookSerializer(books, many=True) # many=True 表示序列化多个对象
    return Response(serializer.data)

    def post(self, request):
        serializer = BookSerializer(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 BookDetail(APIView):
    def get_object(self, pk):
    try:
    return Book.objects.get(pk=pk)
    except Book.DoesNotExist:
    raise status.HTTP_404_NOT_FOUND

    def get(self, request, pk):
        book = self.get_object(pk)
        serializer = BookSerializer(book)
        return Response(serializer.data)
    
    def put(self, request, pk):
        book = self.get_object(pk)
        serializer = BookSerializer(book, 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):
        book = self.get_object(pk)
        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
    

    ```

  • 使用 GenericViewSet (更简洁、推荐):

    ```python
    from rest_framework import viewsets, mixins
    from .models import Book
    from .serializers import BookSerializer

    class BookViewSet(mixins.ListModelMixin,
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    mixins.UpdateModelMixin,
    mixins.DestroyModelMixin,
    viewsets.GenericViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    或者更简洁的使用`ModelViewSet`python
    class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    ```

5. 配置 URL 路由

myapp/urls.py 中配置 URL 路由:

```python
from django.urls import path, include
from rest_framework import routers
from .views import BookList, BookDetail, BookViewSet # 导入你的视图

使用 APIView 的路由

urlpatterns = [
path('books/', BookList.as_view()),
path('books//', BookDetail.as_view()),
]

使用 ViewSet 的路由 (更简洁)

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

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

最后,在 myproject/urls.py 中包含应用的 URL 配置:

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

urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapp.urls')), # 包含应用的 URL
path('api-auth/', include('rest_framework.urls')) # 可选,用于在可浏览 API 中添加登录/登出
]
```

6. 测试 API

现在你可以启动开发服务器并测试你的 API 了:

bash
python manage.py runserver

  • 使用浏览器或 Postman: 访问 http://127.0.0.1:8000/api/books/ 查看书籍列表,以及其他你定义的 URL。
  • 使用 DRF 的可浏览 API: DRF 提供了一个非常方便的可浏览 API 界面,你可以在浏览器中直接查看 API 文档、发送请求、查看响应。

7. 高级特性

  • 认证 (Authentication): DRF 支持多种认证方式,如 Basic Authentication, Token Authentication, Session Authentication, JWT (JSON Web Token) 等。

    ```python

    settings.py

    REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
    'rest_framework.authentication.TokenAuthentication', #使用token认证
    'rest_framework.authentication.SessionAuthentication', # 也可以同时支持 Session 认证
    ],
    # ... 其他配置 ...
    }
    生成token,可以在`views.py`中添加:python
    from rest_framework.authtoken.models import Token
    from django.contrib.auth.models import User

    # 为每个用户创建Token.  你可以在用户注册成功后自动调用。
    for user in User.objects.all():
        Token.objects.get_or_create(user=user)
    

    在请求时,在`headers`中添加:
    Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
    ```

  • 权限 (Permissions): 控制谁可以访问你的 API 的哪些部分。

    ```python

    views.py

    from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny

    class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [IsAuthenticated] # 只有认证用户才能访问

    # 或者为不同的操作设置不同的权限
    def get_permissions(self):
        if self.action == 'list':
            permission_classes = [AllowAny] # 列表允许所有人
        else:
            permission_classes = [IsAdminUser] #其他操作需要管理员
        return [permission() for permission in permission_classes]
    

    ```

  • 限流 (Throttling): 防止 API 被滥用。

    ```python

    settings.py

    REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
    'rest_framework.throttling.AnonRateThrottle', # 匿名用户限流
    'rest_framework.throttling.UserRateThrottle' # 登录用户限流
    ],
    'DEFAULT_THROTTLE_RATES': {
    'anon': '10/day', # 匿名用户每天10次
    'user': '100/day' # 登录用户每天100次
    }
    # ...
    }
    或者在`views.py`中python
    from rest_framework.throttling import UserRateThrottle, AnonRateThrottle

    class BookViewSet(viewsets.ModelViewSet):
    # ...
    throttle_classes = [UserRateThrottle, AnonRateThrottle]
    ```

  • 过滤 (Filtering): 允许客户端根据条件筛选数据。

    ```python

    views.py

    from django_filters.rest_framework import DjangoFilterBackend
    from rest_framework import filters

    class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['author', 'publication_date'] # 允许按作者和出版日期过滤
    search_fields = ['title', 'isbn'] # 允许搜索标题和 ISBN
    ordering_fields = ['title', 'publication_date'] # 允许按标题和出版日期排序
    请求示例:
    /api/books/?author=Tolkien # 过滤作者
    /api/books/?search=Hobbit # 搜索标题
    /api/books/?ordering=-publication_date # 按出版日期降序排序
    ```

  • 分页 (Pagination): 将大量数据分成多个页面返回。

    ```python

    settings.py 已经配置了全局分页

    views.py (如果需要自定义某个视图的分页)

    from 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 # 使用自定义分页
    请求示例:
    /api/books/?page=2 # 获取第 2 页
    /api/books/?page=2&page_size=50 # 获取第 2 页,每页 50 条
    ```

  • 版本控制(Versioning):

    ```python
    # settings.py
    REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning', #最常用的
    # 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.NamespaceVersioning',
    # 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',

     'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
     'VERSION_PARAM': 'version',      # 版本参数名
    

    }
    ```

    python
    # urls.py (使用 URLPathVersioning)
    urlpatterns = [
    path('api/v1/books/', ...), # v1 版本的 URL
    path('api/v2/books/', ...), # v2 版本的 URL
    ]

    python
    # views.py (获取版本)
    class BookViewSet(viewsets.ModelViewSet):
    def list(self, request, *args, **kwargs):
    version = request.version # 获取版本号
    # ... 根据版本号做不同的处理 ...

    8. 总结

本教程详细介绍了如何使用 Django REST Framework 开发 RESTful API。 从基本的模型、序列化器、视图和 URL 配置,到认证、权限、限流、过滤、分页等高级特性,都进行了全面的讲解。 通过学习本教程,你应该能够构建出功能强大、结构良好、易于维护的 API。 记住,DRF 是一个非常灵活的框架,你可以根据自己的需求进行定制和扩展。 始终参考官方文档以获取最新信息和更多高级用法。

THE END