所有文章 > API开发 > 使用Django REST Framework构建API
使用Django REST Framework构建API

使用Django REST Framework构建API

在第一部分中,我将为您介绍如何利用Django REST框架(DRF)与Django快速开发API。本部分旨在激发您的兴趣,让您初步体验使用DRF开发REST API的便捷性,实现快速上手且代码精简。本系列后续部分将深入探索DRF的更高级特性和功能。

传统上,Django被众多开发者誉为MVC Web框架,但它同样适用于构建后端API。接下来,我们将深入了解如何利用它构建后端。

让我们开始吧

在本教程中,您将构建一个针对简单音乐服务的API。

设置您的开发环境

在本教程中,我使用python 3.6.3。您可以通过在shell中键入以下命令来检查本地机器上安装的Python版本;

$ python

执行后,系统将返回一个输出,显示已安装的Python版本号,例如:

Python 3.6.3 (default, Oct  4 2017, 06:09:15)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

对于Linux和Mac OS用户,您可以在CLI中键入此命令以显示已安装的python版本;

$ python -V
Python 3.6.3

由于本教程将使用Django 2.0,因此如果您的开发机器上尚未安装,我建议您安装Python 3.4、3.5或3.6的最新版本。

在安装Python之后,您可以继续执行以下步骤来为您的API项目创建一个工作目录,并设置一个虚拟环境。

对于Linux和Mac OS用户,您可以在命令行界面(CLI)中输入以下命令来设置工作目录和虚拟环境:

$ mkdir music_service && cd music_service
# creates virtual enviroment named venv
music_service$ virtualenv --python=python3 venv
# activate the virtual enviroment named venv
music_service$ source venv/bin/activate

在使用DRF构建API之前,您需要首先在之前创建的虚拟环境中安装django

(venv)music_service$ pip install Django==2.0.3

安装django后,继续在前面创建的虚拟环境中安装djangorestframework

(venv)music_service$ pip install djangorestframework

项目设置

在设置好你的开发环境之后,继续创建一个django项目;

(venv)music_service$ django-admin.py startproject api .
(venv)music_service$ cd api

然后创建一个 Django 应用程序;

(venv)music_service$ django-admin.py startapp music

此时,目录结构现在应如下所示;

api/
manage.py
api/
__init__.py
settings.py
urls.py
wsgi.py
music/
migrations/
__init__.py
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
venv/

在创建项目和应用程序之后,接下来您需要首次同步数据库,并创建一个初始用户,同时为该用户设置密码。

(venv)music_service$ python manage.py migrate
(venv)music_service$ python manage.py createsuperuser --email admin@example.com --username admin

现在,请打开api/settings.py文件,并将rest_frameworkmusic应用程序添加到INSTALLED_APPS配置中。

INSTALLED_APPS = [
...
'rest_framework',
'music'
]

此外,打开api/urls.py文件并为music应用程序添加URL;

...
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('music.urls'))
]

在本教程中,我采用了与Django一同提供的默认SQLite作为关系数据库管理系统(RDBMS),当然,您也可以选择使用PostgreSQL或其他您偏好的RDBMS。

至此,您的项目设置已经完成,接下来就可以开始为音乐服务API编写代码了。

测试驱动开发

没有测试的代码会按设计出错

— 雅各布·卡普兰-莫斯

在着手编写API的业务逻辑之前,编写测试是至关重要的一步。我倾向于先为单个视图编写一个单元测试,然后逐步更新代码以确保该测试能够通过。

编写一个测试

为了演示这种方法,我们将为返回所有歌曲的端点(即GET /songs/)创建一个测试。

请打开music/tests.py文件,并在其中添加相应的代码。

from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from rest_framework.views import status
from .models import Songs
from .serializers import SongsSerializer

# tests for views


class BaseViewTest(APITestCase):
client = APIClient()

@staticmethod
def create_song(title="", artist=""):
if title != "" and artist != "":
Songs.objects.create(title=title, artist=artist)

def setUp(self):
# add test data
self.create_song("like glue", "sean paul")
self.create_song("simple song", "konshens")
self.create_song("love is wicked", "brick and lace")
self.create_song("jam rock", "damien marley")


class GetAllSongsTest(BaseViewTest):

def test_get_all_songs(self):
"""
This test ensures that all songs added in the setUp method
exist when we make a GET request to the songs/ endpoint
"""
# hit the API endpoint
response = self.client.get(
reverse("songs-all", kwargs={"version": "v1"})
)
# fetch the data from db
expected = Songs.objects.all()
serialized = SongsSerializer(expected, many=True)
self.assertEqual(response.data, serialized.data)
self.assertEqual(response.status_code, status.HTTP_200_OK)

此时,如果您尝试运行测试,它将会失败并报错,原因是我们还没有创建视图文件和序列化器。

创建视图

在编写完测试之后,接下来我们需要编写一个视图来处理GET /songs/请求。

模型:首先,我们需要创建一个模型,用于存储歌曲的相关信息,这些信息将在响应中返回。请打开music/models.py文件,并添加以下代码行:

from django.db import models


class Songs(models.Model):
# song title
title = models.CharField(max_length=255, null=False)
# name of artist or group/band
artist = models.CharField(max_length=255, null=False)

def __str__(self):
return "{} - {}".format(self.title, self.artist)

由于我们使用的是Django,因此也可以将模型注册到admin后台。稍后,我们将展示如何利用admin后台来添加歌曲,以便对手动测试这个端点进行辅助。接下来,请将以下代码行添加到music/admin.py文件中:

from django.contrib import admin
from .models import Songs

admin.site.register(Songs)

在那之后,

(venv)music_service$ python manage.py makemigrations

然后迁移;

(venv)music_service$ python manage.py migrate

序列化器:接下来,我们需要创建一个序列化器。序列化器的作用是将复杂的数据类型(例如查询集和模型实例)转换为Python的基本数据类型,这些数据类型随后可以轻松地转换为JSON、XML或其他内容类型。

请新建一个文件music/serializers.py,并向其中添加以下代码行:

from rest_framework import serializers
from .models import Songs


class SongsSerializer(serializers.ModelSerializer):
class Meta:
model = Songs
fields = ("title", "artist")

序列化器还具备反序列化的功能,这意味着在首先验证传入的数据之后,它可以将解析后的数据转换回复杂的数据类型。Django REST framework中的序列化器的工作机制与Django的Form和ModelForm类颇为相似。

视图:现在,我们来创建一个视图,用于返回所有歌曲的信息。请打开music/views.py文件,并向其中添加以下代码行:

from rest_framework import generics
from .models import Songs
from .serializers import SongsSerializer


class ListSongsView(generics.ListAPIView):
"""
Provides a get method handler.
"""
queryset = Songs.objects.all()
serializer_class = SongsSerializer

对于使用Flask背景的开发者来说,在使用Django REST framework(DRF)构建API时,viewsets的概念可能类似于使用Resources。

在之前的代码中,我们通过设置类的queryset属性来明确如何从数据库中检索对象,并通过指定serializer_class来确定用于序列化和反序列化数据的序列化器。

然而,需要注意的是,此处的描述中存在一个小错误:代码中的视图并非继承自generics.viewsetListViewSet(因为这样的类并不存在)。实际上,它可能是继承自DRF提供的某个泛型视图集类,例如viewsets.ModelViewSet,该类结合了多个通用视图的行为,并提供了标准的CRUD操作。

连接视图

在运行测试之前,您必须通过配置 url 来链接视图。

打开music/tests.py文件并添加以下代码行;

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

urlpatterns = [
path('admin/', admin.site.urls),
re_path('api/(?P<version>(v1|v2))/', include('music.urls'))
]

打开music/tests.py文件并添加以下代码行;

from django.urls import path
from .views import ListSongsView


urlpatterns = [
path('songs/', ListSongsView.as_view(), name="songs-all")
]

现在让我们测试一下!

关键时刻已经到来。首先,让我们来运行自动化测试。请执行以下命令:

(venv)music_service$ python manage.py test

shell中的输出应该与此类似;

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
--------------------------------------------------------------------Ran 1 test in 0.010s
OK
Destroying test database for alias 'default'...

您同样可以手动对这个端点进行测试。请在浏览器中访问http://127.0.0.1:8000/admin,然后使用您在项目设置阶段所创建的超级用户账号和密码进行登录。成功登录后,您将会看到一个管理界面。

点击admin界面中的“MUSIC”下的“Songs”,您将会看到一个界面,它可能如下所示:

点击“ADD SONGS”按钮,然后添加几首歌曲用于测试。完成后,请在浏览器中导航到http://127.0.0.1:8000/api/v1/songs。您将会看到一个界面,它列出了您刚刚添加的所有歌曲,并且以JSON格式呈现。

如果你能看到自己添加的歌曲,那就给自己来个掌声吧!恭喜你,你的API已经成功运行了!

额外福利:API 版本控制

API是后端与前端客户端之间的约定。API版本控制的功能在于,它允许你对不同客户端的行为进行更改,并且能够“优雅地”淘汰旧客户端所使用的旧代码。因此,为你的API添加版本控制是一个值得考虑的举措。

要添加版本控制,请打开api/settings.py文件并添加以下代码行。

# ....

REST_FRAMEWORK = {
# When you enable API versioning, the request.version attribute will contain a string
# that corresponds to the version requested in the incoming client request.
'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
}

当启用API版本控制时,request.version属性将包含与传入客户端请求中请求的版本对应的字符串。与下面的示例代码一样,我们可以访问version属性并根据版本号更改API的行为。

# ...

def list(self, request, *args, **kwargs):
if self.request.version == 'v1':
pass
# you can put here business logic that
# is specific to version 1
pass
# You can put here the current version
# business logic

# ...

收获

到目前为止,我们已经见识到使用Django REST framework(DRF)创建API是多么轻松易行。在本教程中,为了保持内容的简洁明了,我只实现了一个API端点,目的是让您初步了解如何使用这个框架但实际上,利用DRF,您可以构建一个功能强大的API。

下表列出了本项目中实现的所有端点的完整清单。如果您想查看API示例的完整实现,请访问我的GitHub仓库,您可以对其进行分叉(fork),并在学习过程中自由地进行尝试和修改。

1
Endpoint
HTTP MethodCRUD MethodResponse
2songs/GETREADGet all songs
3songs/:id/GETREADGet a single song detail
4songs/POSTCREATEAdd a song
5songs/:id/PUTUPDATEUpdate a single song
6songs/:id/DELETEDELETEDelete a single song

使用 DRF 的优势

  1. DRF具有可浏览API功能。此功能支持为API中的每个端点生成人性化的HTML输出。这些页面允许轻松浏览资源,以及使用POSTPUTDELETE向资源提交数据的表单。
  2. DRF 提供了身份验证功能,您可以在视图上使用该功能来验证 API 中资源的请求。
  3. DRF 提供了权限功能,您可以在视图上使用该功能来保护 API 中的资源。
  4. DRF 提供了限制功能,您可以对视图使用该功能来控制客户端可以向 API 发出的请求速率。
  5. DRF 支持筛选。
  6. DRF 支持分页。
  7. 正如我们之前所了解的,DRF 支持 API 版本控制。

其他资源推荐

如果您正在着手构建API,我强烈推荐您查阅以下资源。这些资源是构建API时不可或缺的最佳实践指南。

此外,官方的DRF和Django文档也是您不可或缺的参考资料。

同时,我还发现cdrf.co这个资源非常有用。它详细阐述了DRF框架中所有类的结构和功能,帮助您更深入地了解DRF的底层实现。

在接下来的第二部分中,我将深入探讨DRF中的身份验证和权限机制,并展示如何将这些机制应用于音乐服务API端点。

希望这篇文章对您有所帮助。

原文链接:https://medium.com/backticks-tildes/lets-build-an-api-with-django-rest-framework-32fcf40231e5

#你可能也喜欢这些API文章!