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

举报
宇宙之一粟 发表于 2022/06/27 11:30:02 2022/06/27
【摘要】 前言我们的下一个项目是使用 Django REST Framework 功能的博客 API。 它将具有用户,权限,并允许完整的 CRUD(创建-读取-更新-删除)功能。 我们还将探索视图集,路由器和文档。在本文中,我们将构建博客系统基本的 API 部分。初始化我们的设置与以前相同。 导航到我们的代码目录,并在其中为该项目创建一个名为blogapi的目录。 然后在新的虚拟环境中安装 Djang...

前言

我们的下一个项目是使用 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.py
INSTALLED_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.py
from django.db import models
from 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.py
from 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.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类,在其中我们指定要包括的字段并显式设置要使用的模型。 自定义序列化器有很多方法,但是对于常见的用例(例如,基本的博客),这就是我们所需要的。

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.py
from rest_framework import generics
from .models import Post
from .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。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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