14个文本转图像AI 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_framework
和music
应用程序添加到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 Method | CRUD Method | Response |
2 | songs/ | GET | READ | Get all songs |
3 | songs/:id/ | GET | READ | Get a single song detail |
4 | songs/ | POST | CREATE | Add a song |
5 | songs/:id/ | PUT | UPDATE | Update a single song |
6 | songs/:id/ | DELETE | DELETE | Delete a single song |
使用 DRF 的优势
- DRF具有可浏览API功能。此功能支持为API中的每个端点生成人性化的HTML输出。这些页面允许轻松浏览资源,以及使用
POST
、PUT
和DELETE
向资源提交数据的表单。 - DRF 提供了身份验证功能,您可以在视图上使用该功能来验证 API 中资源的请求。
- DRF 提供了权限功能,您可以在视图上使用该功能来保护 API 中的资源。
- DRF 提供了限制功能,您可以对视图使用该功能来控制客户端可以向 API 发出的请求速率。
- DRF 支持筛选。
- DRF 支持分页。
- 正如我们之前所了解的,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