从零开始构建Django RESTful API:完整教程与代码实战

举报
柠檬味拥抱 发表于 2024/09/08 11:19:42 2024/09/08
【摘要】 在现代Web开发中,RESTful API(Representational State Transfer)已成为构建后端服务的标准模式。它允许客户端通过HTTP请求与服务器进行交互,并支持不同的操作如GET、POST、PUT、DELETE等。Django作为一个流行的Python Web框架,提供了强大的工具和扩展库,帮助开发者快速构建RESTful API。

在现代Web开发中,RESTful API(Representational State Transfer)已成为构建后端服务的标准模式。它允许客户端通过HTTP请求与服务器进行交互,并支持不同的操作如GET、POST、PUT、DELETE等。Django作为一个流行的Python Web框架,提供了强大的工具和扩展库,帮助开发者快速构建RESTful API。

本文将从基础到高级,逐步讲解如何使用Django开发RESTful API,并结合代码实例来帮助理解。

一、基础准备

1. 创建Django项目

首先,我们需要创建一个Django项目并安装必要的依赖。

$ django-admin startproject myproject
$ cd myproject
$ python manage.py startapp api

安装Django REST framework,这是一个用于构建Web API的强大工具包。

$ pip install djangorestframework

settings.py中添加rest_frameworkINSTALLED_APPS

INSTALLED_APPS = [
    ...
    'rest_framework',
    'api',
]
2. 创建模型

为了演示API的基本功能,我们将创建一个简单的模型——Book,表示书籍的基本信息。

# api/models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=255)
    author = models.CharField(max_length=255)
    published_date = models.DateField()

    def __str__(self):
        return self.title

运行迁移命令来创建数据库表:

$ python manage.py makemigrations
$ python manage.py migrate
3. 序列化数据

Django REST framework提供了强大的序列化工具来将模型数据转换为JSON格式。在API中,我们需要创建一个序列化器类。

# api/serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

二、创建基础API视图

Django REST framework提供了多种方式来创建视图。在这里,我们将使用基于类的视图来创建基本的CRUD(创建、读取、更新、删除)API。

# api/views.py
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer

class BookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

class BookRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

接下来,定义API的路由:

# api/urls.py
from django.urls import path
from .views import BookListCreateAPIView, BookRetrieveUpdateDestroyAPIView

urlpatterns = [
    path('books/', BookListCreateAPIView.as_view(), name='book-list-create'),
    path('books/<int:pk>/', BookRetrieveUpdateDestroyAPIView.as_view(), name='book-detail'),
]

在主项目的urls.py中包含这些路由:

# myproject/urls.py
from django.contrib import admin
from django.urls import path, include

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

至此,我们已经构建了一个基本的RESTful API。通过/api/books/,客户端可以获取所有书籍列表,或创建新的书籍;通过/api/books/<id>/,可以获取、更新或删除特定书籍。

三、高级功能实现

1. 添加分页和过滤

当数据库中的数据量增加时,分页和过滤成为API中常用的功能。Django REST framework提供了内置的分页支持。

settings.py中配置分页:

# myproject/settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}

接下来,我们可以通过Django REST framework的django-filter库来添加过滤功能:

$ pip install django-filter

settings.py中配置过滤器:

# myproject/settings.py
REST_FRAMEWORK = {
    ...
    'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}

在视图中启用过滤:

# api/views.py
from django_filters.rest_framework import DjangoFilterBackend

class BookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ['author', 'published_date']

现在,客户端可以通过/api/books/?author=AuthorName/api/books/?published_date=2024-01-01等查询参数来过滤结果。

2. 实现权限控制和认证

在实际应用中,某些API需要保护,只有经过认证的用户才可以访问。Django REST framework支持多种认证机制,如Token认证、JWT认证等。

安装djangorestframework-simplejwt来实现JWT认证:

$ pip install djangorestframework-simplejwt

settings.py中配置JWT认证:

# myproject/settings.py
REST_FRAMEWORK = {
    ...
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

接下来,在视图中添加权限控制:

# api/views.py
from rest_framework.permissions import IsAuthenticated

class BookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [IsAuthenticated]
3. 性能优化:使用缓存和查询优化

在高并发的环境中,API性能优化至关重要。Django提供了多种缓存机制,可以用于API的性能优化。

在视图中使用缓存装饰器:

from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

class BookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    @method_decorator(cache_page(60*2))  # 缓存2分钟
    def get(self, request, *args, **kwargs):
        return super().get(request, *args, **kwargs)

同时,为了避免不必要的数据库查询,可以使用select_relatedprefetch_related来优化查询:

class BookListCreateAPIView(generics.ListCreateAPIView):
    queryset = Book.objects.select_related('author').all()  # 假设author是外键
    serializer_class = BookSerializer

四、测试API

在构建完RESTful API后,测试是确保API功能正确、性能可靠的关键步骤。Django REST framework提供了强大的测试工具,使我们能够轻松地为API编写测试用例。

1. 编写单元测试

首先,我们为Book API编写一些单元测试。Django的测试框架基于Python的unittest模块,并通过TestCase类提供了对数据库操作的支持。

# api/tests.py
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from .models import Book

class BookAPITestCase(APITestCase):

    def setUp(self):
        self.book = Book.objects.create(
            title="Sample Book",
            author="John Doe",
            published_date="2024-01-01"
        )
        self.list_url = reverse('book-list-create')
        self.detail_url = reverse('book-detail', kwargs={'pk': self.book.pk})

    def test_get_book_list(self):
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data), 1)

    def test_create_book(self):
        data = {
            "title": "New Book",
            "author": "Jane Doe",
            "published_date": "2024-05-05"
        }
        response = self.client.post(self.list_url, data)
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Book.objects.count(), 2)

    def test_update_book(self):
        data = {
            "title": "Updated Book",
            "author": "John Smith",
            "published_date": "2024-01-01"
        }
        response = self.client.put(self.detail_url, data)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.book.refresh_from_db()
        self.assertEqual(self.book.title, "Updated Book")
        self.assertEqual(self.book.author, "John Smith")

    def test_delete_book(self):
        response = self.client.delete(self.detail_url)
        self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
        self.assertEqual(Book.objects.count(), 0)

在以上测试用例中,我们测试了以下功能:

  • 获取书籍列表:通过GET请求验证API是否能够正确返回所有书籍。
  • 创建书籍:通过POST请求验证API是否能够创建新书籍,并确保数据正确存储。
  • 更新书籍:通过PUT请求验证API是否能够正确更新书籍信息。
  • 删除书籍:通过DELETE请求验证API是否能够删除指定书籍。
2. 测试权限和认证

在涉及权限和认证的API中,我们还需要测试用户访问的权限,确保未经授权的用户无法访问受保护的资源。

# api/tests.py
from rest_framework.test import APIClient

class BookAPITestCase(APITestCase):

    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(username='testuser', password='testpass')
        self.client.force_authenticate(user=self.user)
        ...

    def test_unauthenticated_access(self):
        self.client.force_authenticate(user=None)
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

    def test_authenticated_access(self):
        response = self.client.get(self.list_url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)

在这里,我们首先创建了一个测试用户,并验证了未经认证的请求是否会被拒绝(返回401状态码),而认证用户能够正常访问资源。

五、API文档生成

良好的API文档能够帮助开发者和使用者更好地理解和使用API。Django REST framework支持通过Swagger、ReDoc等工具生成API文档。

1. 使用drf-yasg生成Swagger文档

drf-yasg是一个用于生成Swagger文档的第三方库,它能够自动生成交互式API文档。

首先安装drf-yasg

$ pip install drf-yasg

在项目的urls.py中添加Swagger文档的路由:

# myproject/urls.py
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
   openapi.Info(
      title="Book API",
      default_version='v1',
      description="Test description",
   ),
   public=True,
   permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    ...
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
]

通过访问/swagger/路径,您可以查看生成的API文档,并进行交互测试。

2. 使用ReDoc生成文档

ReDoc是另一种API文档生成工具,它提供了美观的静态文档页面。

urls.py中添加ReDoc路由:

# myproject/urls.py
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
   openapi.Info(
      title="Book API",
      default_version='v1',
      description="Test description",
   ),
   public=True,
   permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    ...
    path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

通过访问/redoc/路径,您可以查看使用ReDoc生成的静态文档。

六、部署Django RESTful API

当API开发完成后,部署是使其对外可用的关键步骤。我们将简要介绍如何将Django RESTful API部署到生产环境。

1. 使用Gunicorn和Nginx部署

Gunicorn是一个用于运行Django应用的WSGI HTTP服务器,Nginx可以作为反向代理来处理静态文件和分发请求。

首先,安装Gunicorn:

$ pip install gunicorn

然后,使用以下命令启动Gunicorn:

$ gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

接下来,配置Nginx,将请求代理到Gunicorn:

server {
    listen 80;
    server_name mydomain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static/ {
        alias /path/to/static/;
    }

    location /media/ {
        alias /path/to/media/;
    }
}

最后,启动Nginx并确保Gunicorn和Nginx一同启动,您的API将可以通过域名或IP地址访问。

2. 配置环境变量和安全设置

为了在生产环境中安全地运行Django应用,我们需要配置环境变量并设置安全选项。在生产中,应将DEBUG设为False,并使用环境变量来管理敏感信息。

export DJANGO_SECRET_KEY='your-secret-key'
export DJANGO_ALLOWED_HOSTS='yourdomain.com'
export DJANGO_DEBUG=False

settings.py中读取这些环境变量:

import os

SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
DEBUG = os.getenv('DJANGO_DEBUG') == 'True'
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS').split(',')

通过这些步骤,您可以确保Django RESTful API在生产环境中安全、可靠地运行。

七、API版本控制

随着API的发展和迭代,API的版本控制变得至关重要。版本控制可以确保旧版本的客户端仍然能够正常工作,同时允许我们在新版本中引入改进和更改。

1. URL版本控制

最简单的版本控制方法是通过URL路径来区分不同版本的API:

# myproject/urls.py
urlpatterns = [
    path('api/v1/', include('api.v1.urls')),
    path('api/v2/', include('api.v2.urls')),
]

在这个结构中,不同版本的API可以在各自的URL配置文件中定义。例如,api/v1/urls.pyapi/v2/urls.py分别对应不同版本的路由和视图。

2. 使用Accept Header进行版本控制

另一种更为优雅的方式是使用HTTP的Accept头来管理API版本。Django REST framework支持通过自定义的版本类来实现这种方式。

首先,在settings.py中定义版本控制:

# myproject/settings.py
REST_FRAMEWORK = {
    ...
    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.AcceptHeaderVersioning',
    'DEFAULT_VERSION': 'v1',
    'ALLOWED_VERSIONS': ['v1', 'v2'],
    'VERSION_PARAM': 'version',
}

接下来,在视图中基于版本进行逻辑处理:

# api/views.py
from rest

_framework.views import APIView
from rest_framework.response import Response

class BookListCreateAPIView(APIView):

    def get(self, request, *args, **kwargs):
        if request.version == 'v1':
            # 返回v1版本的数据格式
        elif request.version == 'v2':
            # 返回v2版本的数据格式
        return Response(data)

客户端在请求时通过Accept头指定所需的版本:

GET /api/books/ HTTP/1.1
Accept: application/json; version=v2

八、总结

在本教程中,我们详细探讨了如何使用Django构建一个RESTful API。我们从安装和设置环境开始,逐步讲解了如何设计和实现API的各个部分,包括序列化、视图、权限和认证、版本控制,以及如何测试和部署API。

Django REST framework为构建RESTful API提供了强大的工具和灵活的架构,适合各种复杂度的应用开发。通过学习和实践,您将能够构建出功能强大、性能卓越的API,为您的应用提供可靠的后端支持。

84f571cae78b4d9098da25990dd2e36.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。