测试
让我们为 Post 模型编写一个基本测试。 我们希望确保已登录的用户可以创建带有标题和正文的博客文章。
# posts/tests.py from django.test import TestCase from django.contrib.auth.models import User from .models import Post class BlogTests(TestCase): @classmethod def setUpTestData(cls): # Create a user testuser1 = User.objects.create_user(username='testuser1', password='abc123') testuser1.save() # Create a blog post test_post = Post.objects.create( author=testuser1, title='Blog title', body='Body content...' ) test_post.save() def test_blog_content(self): post = Post.objects.get(id=1) author = f'{post.author}' title = f'{post.title}' body = f'{post.body}' self.assertEqual(author, 'testuser1') self.assertEqual(title, 'Blog title') self.assertEqual(body, 'Body content...')
为了确认我们的测试正常,请退出本地服务器 Control + c。 然后运行我们的测试。
(blogapi) $ python manage.py test
您应该看到类似以下的输出,该输出确认一切正常。
(blogapi) $ python manage.py test Creating test database for alias 'default'... System check identified no issues (0 silenced). . ---------------------------------------------------------------------- Ran 1 test in 0.119s OK Destroying test database for alias 'default'...
现在,我们已经完成了 API 的常规 Django 部分。 我们真正需要的只是模型和数据库中的一些数据。 现在是时候添加 Django REST 框架,以将我们的模型数据转换为 API 了。
Django REST Framework
如前所述,Django REST Framework 负责将数据库模型转换为 RESTful API 的繁重工作。 此过程包括三个主要步骤:
- URL 路由的
urls.py
文件 - 将数据转换为 JSON 的
serializers.py
- 将应用逻辑用于每个 API 端点的
views.py
文件
在命令行中,使用 Control + c 停止本地服务器,然后使用 pipenv 安装 Django REST Framework。
(blogapi) $ pipenv install djangorestframework==3.10.3
然后将其添加到 settings.py 文件的 INSTALLED_APPS 部分。 明确设置我们的权限也是个好主意,默认情况下,Django REST Framework 中的权限已配置为 AllowAny
。 我们将在下一章中进行更新。
# blog_project/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 3rd-party apps 'rest_framework', # new # Local 'posts.apps.PostsConfig', ] # new REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ] }
现在,我们需要创建 URL,视图和序列化程序。
URLs
让我们从端点的实际位置的 URL 路由开始。 使用第二行的 include import 和我们的 posts app 的新api/v1/
路由更新项目级别的 urls.py 文件。
# blog_project/urls.py from django.contrib import admin from django.urls import include, path # new urlpatterns = [ path('admin/', admin.site.urls), path('api/v1/', include('posts.urls')), # new ]
最好始终对 API(v1 /,v2 /等)进行版本控制,因为进行较大的更改时,可能需要一段时间才能使 API 的各个使用者进行更新。 这样,您可以在一段时间内支持 API 的 v1,同时还可以启动新的更新的 v2,并避免破坏依赖于 API 后端的其他应用程序。
请注意,由于目前我们唯一的应用是 posts,因此我们可以直接在此处添加博客。 如果我们在一个项目中有多个应用程序,那么最好创建一个专用的 api 应用程序,然后将所有其他 API url 路由包含到其中。 但是对于像这样的基础项目,我宁愿避免使用仅用于路由的 api 应用。 如有需要,我们随时可以添加一个。
接下来,创建我们的帖子应用 urls.py 文件。
(blogapi) $ touch posts/urls.py
然后包含以下代码。
# posts/urls.py from django.urls import path from .views import PostList, PostDetail urlpatterns = [ path('<int:pk>/', PostDetail.as_view()), path('', PostList.as_view()), ]
所有博客路由都将位于 api/v1/
上,因此我们的 PostList 视图(我们将很快写出)的 ''
将位于 api/v1/
上,而 PostDetail
视图(也将被写入)位于 api/v1/#
其中 #
表示条目的主键。 例如,第一篇博文的主要 ID 为 1,因此它将位于路由 api/v1/1
处,第二篇博文的 API 为 api/v1/2
,依此类推。
Serializers
现在为我们的序列化函数。 在我们的 posts 应用中创建一个新的serializers.py
文件。
(blogapi) $ touch posts/serializers.py
序列化器不仅可以将数据转换为 JSON,还可以指定要包括或排除的字段。 在我们的例子中,我们将包括 Django 自动添加到数据库模型的 id 字段,但由于不将 update_at 字段包含在我们的字段中,因此我们将排除它。
在我们的 API 中轻松包含/排除字段的功能是一项了不起的功能。 通常,基础数据库模型具有的字段远远多于需要公开的字段。 Django REST Framework 强大的序列化程序类使控制它非常简单。
# posts/serializers.py from rest_framework import serializers from .models import Post class PostSerializer(serializers.ModelSerializer): class Meta: fields = ('id', 'author', 'title', 'body', 'created_at',) model = Post
在文件的顶部,我们导入了 Django REST Framework 的 serializers 类和我们自己的模型。 然后,我们创建了一个 PostSerializer,并添加了一个 Meta 类,在其中我们指定要包括的字段并显式设置要使用的模型。 自定义序列化器有很多方法,但是对于常见的用例(例如,基本的博客),这就是我们所需要的。