写点什么

Django API 开发:博客系统接入 API

作者:宇宙之一粟
  • 2022 年 6 月 05 日
  • 本文字数:5057 字

    阅读完需:约 17 分钟

Django API 开发:博客系统接入 API

前言

我们的下一个项目是使用 Django REST Framework 功能的博客 API。 它将具有用户,权限,并允许完整的 CRUD(创建-读取-更新-删除)功能。 我们还将探索视图集,路由器和文档。


在本文中,我们将构建博客系统基本的 API 部分。

初始化

我们的设置与以前相同。 导航到我们的代码目录,并在其中为该项目创建一个名为 blogapi 的目录。 然后在新的虚拟环境中安装 Django,创建新的 Django 项目(blog_project)和用于博客条目(posts)的应用。


$ cd ~/Desktop && cd code$ mkdir blogapi && cd blogapi$ pipenv install django==2.2.6$ pipenv shell(blogapi) $ django-admin startproject blog_project . (blogapi) $ python manage.py startapp posts
复制代码


由于我们添加了新应用,因此我们需要将其告知 Django。 因此,请确保在 settings.py 文件中将帖子添加到我们的 INSTALLED_APPS 列表中。


# blog_project/settings.pyINSTALLED_APPS = [     'django.contrib.admin',     'django.contrib.auth',     'django.contrib.contenttypes',     'django.contrib.sessions',     'django.contrib.messages',     'django.contrib.staticfiles',
# Local 'posts.apps.PostsConfig', # new ]
复制代码


现在,第一次运行 migrate,将我们的数据库与 Django 的默认设置和新应用同步。


(blogapi) $ python manage.py migrate
复制代码

模型

我们的数据库模型将包含五个字段:author,title,body,created_at 和 updated_at。 如果我们在顶部的第二行中导入了 Django 的内置用户模型,则可以使用该模型。


# posts/models.pyfrom django.db import modelsfrom django.contrib.auth.models import User

class Post(models.Model): author = models.ForeignKey(User, on_delete=models.CASCADE) title = models.CharField(max_length=50) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
def __str__(self): return self.title
复制代码


请注意,我们还定义了模型的__str__表示形式,这是 Django 的最佳做法。 这样,我们稍后将在 Django 管理员中看到标题。现在,通过首先创建一个新的迁移文件,然后运行迁移将数据库与我们的模型更改同步来更新数据库。


(blogapi) $ python manage.py makemigrations posts (blogapi) $ python manage.py migrate
复制代码


好! 我们想在 Django 出色的内置管理应用程序中查看数据,因此,如下所示将其添加到 posts/admin.py 中。


# posts/admin.pyfrom django.contrib import admin from .models import Post

admin.site.register(Post)
复制代码


然后创建一个超级用户帐户,以便我们可以访问管理员。 在下面键入命令,然后输入所有提示。


(blogapi) $ python manage.py createsuperuser
复制代码


现在我们可以启动本地 Web 服务器。


导航到 http://127.0.0.1:8000/admin/ 并使用您的超级用户凭据登录。


单击帖子旁边的“ +Add”按钮,然后创建一个新博客帖子。“作者”旁边将是一个具有您的超级用户帐户的下拉菜单(我的帐户称为 wsv)。 确保选择了作者。 添加标题和正文内容,然后单击“保存”按钮。


您将被重定向到显示所有现有博客帖子的“帖子”页面。



测试

让我们为 Post 模型编写一个基本测试。 我们希望确保已登录的用户可以创建带有标题和正文的博客文章。


# posts/tests.pyfrom django.test import TestCasefrom django.contrib.auth.models import Userfrom .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 testCreating test database for alias 'default'...System check identified no issues (0 silenced).. ---------------------------------------------------------------------- Ran 1 test in 0.119s
OKDestroying 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.pyINSTALLED_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', ]
# newREST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ]}
复制代码


现在,我们需要创建 URL,视图和序列化程序。

URLs

让我们从端点的实际位置的 URL 路由开始。 使用第二行的 include import 和我们的 posts app 的新api/v1/路由更新项目级别的 urls.py 文件。


# blog_project/urls.pyfrom django.contrib import adminfrom 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.pyfrom django.urls import pathfrom .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.pyfrom 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 类,在其中我们指定要包括的字段并显式设置要使用的模型。 自定义序列化器有很多方法,但是对于常见的用例(例如,基本的博客),这就是我们所需要的。

Views

最后一步是创建我们的视图。 Django REST Framework 具有几个有用的通用视图。 我们已经在 Library API 和 Todos API 中都使用ListAPIView来创建一个只读端点集合,实质上是所有模型实例的列表。 在 Todos API 中,我们还将RetrieveAPIView用作只读的单个端点,这类似于传统 Django 中的详细信息视图。


对于我们的 Blog API,我们希望将所有可用的博客文章列出为读写端点,这意味着使用ListCreateAPIView,它类似于我们之前使用的 ListAPIView,但允许写操作。 我们还希望使各个博客帖子可供阅读,更新或删除。 可以肯定的是,有一个内置的通用 Django REST Framework 视图正用于此目的:RetrieveUpdateDestroyAPIView。 这就是我们在这里使用的。


更新view.py文件,如下:


# posts/views.pyfrom rest_framework import genericsfrom .models import Postfrom .serializers import PostSerializer
class PostList(generics.ListCreateAPIView): queryset = Post.objects.all() serializer_class = PostSerializer
class PostDetail(generics.RetrieveUpdateDestroyAPIView): queryset = Post.objects.all() serializer_class = PostSerializer
复制代码


在文件的顶部,我们从 Django REST Framework 以及模型和序列化器文件导入泛型。 然后,我们创建两个视图。 PostList 使用通用的 ListCreateAPIView,而 PostDetail 使用 RetrieveUpdateDestroyAPIView。


我们要做的就是更新通用视图以从根本上改变给定 API 端点的行为,这非常令人惊讶。 这是使用诸如 Django REST Framework 之类的功能齐全的框架的优势:所有这些功能都是可用的,经过测试的并且可以正常使用。 作为开发人员,我们不必在这里重新发明轮子。


至此,我们的 API 现在已经完成,我们真的不必自己编写太多代码。 在接下来的章节中,我们将对 API 进行其他改进,但是值得一提的是,它已经执行了我们想要的基本列表和 CRUD 功能。 是时候使用 Django Rest Framework 的可浏览 API 进行测试了。

Browsable API

启动本地服务器以与我们的 API 进行交互。


(blogapi) $ python manage.py runserver
复制代码


然后转到 http://127.0.0.1:8000/api/v1/ 查看博客列表终端。



该页面以 JSON 格式显示了我们的博客文章列表(目前只有一个)。 注意,GET 和 POST 方法都被允许。


现在,让我们确认是否存在我们的模型实例终结点,该终结点与单个帖子而不是所有帖子的列表有关。


转到 http://127.0.0.1:8000/api/v1/1/.



您可以在标头中看到支持 GET,PUT,PATCH 和 DELETE,但不支持 POST。 实际上,您可以使用下面的 HTML 表单进行更改,甚至可以使用红色的“ DELETE”按钮删除实例。


让我们尝试一下。 最后用其他文字(已编辑)更新标题。 然后点击“ PUT”按钮。


通过单击页面顶部的链接返回到“帖子列表”视图,或直接导航到 http://127.0.0.1:8000/api/v1/,您也可以在那里查看更新的文本。



总结

此时,我们的 Blog API 完全可用。 但是,有一个大问题:任何人都可以更新或删除现有博客文章! 换句话说,我们没有任何权限。 在下一篇文章中,我们将学习如何应用权限来保护我们的 API。

发布于: 刚刚阅读数: 3
用户头像

宇宙古今无有穷期,一生不过须臾,当思奋争 2020.05.07 加入

🏆InfoQ写作平台-第二季签约作者 🏆 混迹于江湖,江湖却没有我的影子 热爱技术,专注于后端全栈,轻易不换岗 拒绝内卷,工作于软件工程师,弹性不加班 热衷分享,执着于阅读写作,佛系不水文

评论

发布
暂无评论
Django API 开发:博客系统接入 API_django_宇宙之一粟_InfoQ写作社区