共计 9345 个字符,预计需要花费 24 分钟才能阅读完成。
download:图灵 JAVA 互联网架构师五期
Django API 开发:一个 Todo 利用的后端
引言
本文中,咱们将学习利用 Django 构建一个 Todo(待办事项)利用的 API 后端,而后将其与 React 前端连接。咱们已经制作了第一个 API,并回顾了 HTTP 和 REST 的工作原理,然而您仍然可能还没有“残缺”了解它们如何拆散在一起。
咱们将创建一个 todo 结构,其中蕴含咱们的后端 Django Python 代码和咱们的前端 React JavaScript 代码。
最终的布局将如下所示。
todo
| ├──frontend
| ├──React…
| ├──backend
| ├──Django…
复制代码
初始化创建后端利用
任何 Django API 的第一步始终是安装 Django,而后在其之上增加 Django REST Framework。首先在桌面上的代码目录中创建一个专用的 todo 目录。
打开一个新的命令行控制台,而后输出以下命令:
$ cd ~/Desktop
$ cd code
$ mkdir todo && cd todo
复制代码
注意:确保已从上一章中停用了虚拟环境。您可能通过键入退出来执行此操作。命令行后面是否没有括号?好。那么您就不在现有的虚拟环境中。
在此 todo 文件夹中将是咱们的后端和前端目录。让咱们创建一个后端文件夹,安装 Django,而后激活一个新的虚拟环境。
$ mkdir backend && cd backend
$ pipenv install django==2.2.6
$ pipenv shell
复制代码
您应该在命令行上看到括号,以确认虚拟环境(后端)已激活。
现在已经安装了 Django,咱们应该首先创建一个传统的 Django 我的项目 todo_project,在其中增加第一个应用程序 todo,而后迁徙初始数据库。
(backend) $ django-admin startproject todo_project . (backend) $ python manage.py startapp todos
(backend) $ python manage.py migrate
复制代码
在 Django 中,咱们始终需要将新利用增加到 INSTALLED_APPS 设置中,所以现在就这样做。在文本编辑器中打开 todo_project/settings.py。在文件底部,增加 todos.apps.TodosConfig。
todo_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Local
'todos.apps.TodosConfig', # new
]
复制代码
如果您现在在命令行上运行 python manage.py runserver 并导航至 http://127.0.0.1:8000/,则可能看到咱们的我的项目已胜利安装。
筹备开始吧!
Models
接下来是在 todo 应用程序中定义咱们的 Todo 数据库模型。咱们将保持基本状态,只有两个字段:title 和 body。
todos/models.py
from django.db import models
class Todo(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
def __str__(self):
return self.title
复制代码
咱们在顶部导入模型,而后将其子类化以创建自己的 Todo 模型。咱们还增加了 str 方法,认为每个将来的模型实例提供易于理解的名称。
因为咱们已经更新了模型,现在该是 Django 进行两步操作的时候了:制作一个新的迁徙文件,而后每次将数据库与更改同步。在命令行上,键入 Control + c 以停止咱们的本地服务器。而后运行以下两个命令:
(backend) $ python manage.py makemigrations todos
(backend) $ python manage.py migrate
复制代码
可能抉择增加咱们要为其创建迁徙文件的特定应用程序(咱们可能只键入 python manage.py makemigrations),但这是采纳的最佳做法。迁徙文件是调试应用程序的一种绝妙方法,您应该致力为每个小的更改创建一个迁徙文件。如果咱们在两个不同的应用程序中更新了模型,而后运行 python manage.py makemigrations,则生成的单个迁徙文件将蕴含两个应用程序中的数据。这只会减少调试难度。尝试使您的迁徙尽可能小。
现在,咱们可能使用内置的 Django 管理应用程序与咱们的数据库进行交互。如果咱们立即进入管理员,咱们的 Todo 应用程序将不会出现。咱们需要通过 todos/admin.py 文件显式增加它,如下所示。
todos/admin.py
from django.contrib import admin
from .models import Todo
admin.site.register(Todo)
复制代码
而已!现在,咱们可能创建一个超级用户帐户来登录管理员。
(backend) $ python manage.py createsuperuser
复制代码
而后再次启动本地服务器:
(backend) $ python manage.py runserver
复制代码
现在,如果您浏览至 http://127.0.0.1:8000/admin/,则可能登录到这个零碎。
单击 Todos 旁边的“+Add”,并创建 3 个新的待办事项,并确保为两者增加题目和注释。如图:
至此,咱们实际上已经实现了 Todo API 的传统 Django 部分。因为咱们不必为该我的项目建立网页,因此不需要网站 URL,视图或模板。咱们需要的只是一个模型,而 Django REST Framework 将负责其余的工作。
Dajngo REST 框架
停止本地服务器 Control + c,而后通过 pipenv 安装 Django REST Framework。
(backend) $ pipenv install djangorestframework==3.10.3
复制代码
而后像其余任何第三方应用程序一样,将 rest_framework 增加到咱们的 INSTALLED_APPS 设置中。咱们还心愿开始配置所有 REST_FRAMEWORK 下存在的 Django REST Framework 特定设置。首先,咱们将权限明确设置为 AllowAny。此行位于文件的底部。
todo_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
'rest_framework', # new
# Local
'todos.apps.TodosConfig',
]
new
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.AllowAny',]
}
复制代码
Django REST Framework 蕴含简短的隐式设置默认设置列表。您可能在此处查看完整列表。AllowAny 是其中之一,这意味着当咱们像下面所做的那样显式设置它时,其成果与没有设置 DEFAULT_PERMISSION_CLASSES 的配置残缺雷同。
好的,这样就安装了 Django REST Framework。
相同,咱们将更新三个特定于 Django REST 框架的文件,以将数据库模型转换为 Web API:urls.py,views.py 和 serializers.py。
URLs
我喜爱先从 URL 开始,因为它们是咱们 API 端点的入口点。就像在传统的 Django 我的项目中一样,urls.py 文件使咱们可能配置路由。
从 Django 我的项目级文件 todo_project/urls.py 开始。咱们在第二行导入 include,并在 api/ 为咱们的 todo 利用增加一条路线。
todo_project/urls.py
from django.contrib import admin
from django.urls import include, path # new
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('todos.urls')), # new
]
复制代码
接下来,创建咱们的应用程序级别的 todos/urls.py 文件。
(backend) $ touch todos/urls.py
复制代码
并使用以下代码对其进行更新。
todos/urls.py
from django.urls import path
from .views import ListTodo, DetailTodo
urlpatterns = [
path('/', DetailTodo.as_view()),
path('', ListTodo.as_view()),
]
复制代码
请注意,咱们引用的还有两个尚未创建的视图:ListTodo 和 DetailTodo。然而,路由现已实现。api/ 有所有待办事项的列表位于空字符串 ”,即。每个待办事项都将在其主键上可用,这是 Django 在每个数据库表中主动设置的值。第一个条目是 1,第二个条目是 2,依此类推。因此,咱们的第一个待办事项最终将位于 API 端点 api/1/。
Serializers
让咱们回顾一下到目前为止。咱们从一个传统的 Django 我的项目和应用程序开始,咱们创建了数据库模型并增加了数据。而后,咱们安装了 Django REST Framework 并配置了 URL。现在,咱们需要将模型中的数据转换为将在 URL 输入的 JSON。因此,咱们需要一个序列化器。
Django REST Framework 附带了一个弱小的内置序列化程序类,咱们可能使用大量代码疾速扩大它们。这就是咱们在这里要做的。
首先在 todos 利用中创建一个新的 serializers.py 文件。
(backend) $ touch todos/serializers.py
复制代码
而后更新代码,如下所示:
todos/serializers.py
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'body',)
复制代码
在顶部,咱们从 Django REST Framework 以及咱们的 models.py 文件导入了序列化器。接下来,咱们创建一个类 TodoSerializer。这里的格局与咱们在 Django 本身中创建模型类或表单的形式非常相似。咱们正在指定要使用的模型以及咱们要公开的特定字段。请记住,id 是 Django 主动创建的,因此咱们不必在 Todo 模型中定义它,然而咱们将在细节视图中使用它。
就是这样。Django REST Framework 现在将神奇地将咱们的数据转换为 JSON,从而公开来自 Todo 模型的 id,title 和 body 字段。
咱们需要做的最初一件事是配置咱们的 views.py 文件。
Views
在传统的 Django 中,视图用于自定义要发送到模板的数据。在 Django REST Framework 中,视图执行雷同的操作,但对序列化的数据而言。
Django REST Framework 视图的语法故意与惯例 Django 视图非常相似,就像惯例 Django 一样,Django REST Framework 随附了通用视图以用于常见用例。这就是咱们在这里使用的。
更新 todos/views.py 文件,如下所示:
todos/views.py
from rest_framework import generics
from .models import Todo
from .serializers import TodoSerializer
class ListTodo(generics.ListAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
class DetailTodo(generics.RetrieveAPIView):
queryset = Todo.objects.all()
serializer_class = TodoSerializer
复制代码
在顶部,咱们导入 Django REST Framework 的泛型视图以及咱们的 models.py 和 serializers.py 文件。
从咱们的 todos/urls.py 文件中调用,咱们有两条道路,因此有两个不同的视图。咱们将使用 ListAPIView 浮现所有待办事项,并使用 RetrieveAPIView 浮现单个模型实例。
精明的读者会留意到这里的代码有些冗余。即使扩大的通用视图有所不同,咱们实质上还是为每个视图重复使用 queryset 和 serializer_class。
然而现在咱们实现了!咱们的 API 已准备就绪,可能使用。如您所见,Django REST Framework 和 Django 之间的唯一真正区别是,使用 Django REST Framework,咱们需要增加 serializers.py 文件,而无需模板文件。否则,urls.py 和 views.py 文件的内容一样。
Consuming the API
传统上使用 API 是一个挑战。对于给定的 HTTP 响应或请求的注释和标头中蕴含的所有信息,根本没有很好的可视化成果。
取而代之的是,大多数开发人员使用命令行 HTTP 客户端(例如 cURL)。
2012 年,第三方软件产品 Postman 投放市场,现在寰球有数百万心愿通过可视化,功能丰富的形式与 API 交互的开发人员使用。
然而 Django REST 框架最令人惊奇的事件之一是,它附带了功能弱小的可浏览 API,咱们可能立即使用它。如果您发现需要使用 API 进行更多自定义,则可能使用 Postman 之类的工具。然而通常内置的可浏览 API 入不敷出。
Browsable API
现在让咱们使用可浏览的 API 与咱们的数据进行交互。确保本地服务器正在运行。
(backend) $ python manage.py runserver
复制代码
而后导航到 http://127.0.0.1:8000/api/ 以查看咱们的工作 API 列表视图端点。
该页面浮现了咱们先前在数据库模型中创建的三个待办事项。
首先,让咱们看一下原始的 JSON 视 图,即实际通过互联网传输的视图。单击右上角的“GET”按钮,而后抉择 JSON。
如果您返回 http://127.0.0.1:8000/api/ 的列表视图页面,咱们可能看到其余信息。回忆一下,HTTP 动词 GET 用于读取数据,而 POST 用于更新或创建数据。
在“列表待办事项”下浮现 GET/api/,它告诉咱们咱们在此端点上执行了 GET。下方浮现的是 HTTP 200 OK,这是咱们的状态代码,一切正常。最重要的是,它上面浮现容许:GET,HEAD,OPTIONS。请注意,因为这是一个只读端点,因此不包含 POST,咱们只能执行 GET。
咱们还为每个模型制作了一个 DetailTodo 视图。这称为实例,在 http://127.0.0.1:8000/api/1/ 上可见。
您也可能导航至以下端点:
http://127.0.0.1:8000/api/2
http://127.0.0.1:8000/api/3
CORS
咱们需要做的最初一步是跨源资源共享(CORS)。每当客户端与不同域(mysite.com 与 yoursite.com)或端口(localhost:3000 与 localhost:8000)上托管的 API 进行交互时,都会存在潜在的安全问题。
具体来说,CORS 申请服务器蕴含特定的 HTTP 标头,以容许客户端必定是否以及何时应容许跨域请求。
咱们的 Django API 后端将与专用前端通信,该前端位于用于本地开发的不同端口上,并在部署后位于另一个域上。
处理此问题的最简单方法(以及 Django REST 框架倡导的一种方法)是使用中间件,该中间件将根据咱们的设置主动包含失当的 HTTP 标头。
咱们将使用的软件包是 django-cors-header,可能轻松将其增加到咱们现有的我的项目中。
首先使用 Control + c 退出咱们的服务器,而后使用 Pipenv 安装 django-cors-headers。
(backend) $ pipenv install django-cors-headers==3.1.1
复制代码
接下来,在三个地位更新咱们的 settings.py 文件:
将 corsheaders 增加到 INSTALLED_APPS
在 MIDDLEWARE 中把 CorsMiddleware 增加到 CommonMiddleWare 的上方
创建一个 CORS_ORIGIN_WHITELIST
todo_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
'rest_framework',
'corsheaders', # new
# Local
'todos.apps.TodosConfig',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # new
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
new
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://localhost:8000',
)
复制代码
将 corsheaders.middleware.CorsMiddleware 出现在正确的地位非常重要。因为中间件是从上到下加载的,因此它位于 MIDDLEWARE 设置中的 django.middleware.common.CommonMiddleware 之上。另外请注意,咱们已将两个域列入白名单:localhost:3000 和 localhost:”8000。前者是 React 的默认端口,下一章将在前端使用它。后者是默认的 Django 端口。
测试
您应该始终为 Django 我的项目编写测试。后期花费的大量工夫将为您俭约大量的工夫和当前的调试谬误。让咱们增加两个基本测试,以确认题目和注释内容的行为符合预期。
打开 todos/tests.py 文件,并增加以下内容:
todos/tests.py
from django.test import TestCase
from .models import Todo
class TodoModelTest(TestCase):
@classmethod
def setUpTestData(cls):
Todo.objects.create(title='first todo', body='a body here')
def test_title_content(self):
todo = Todo.objects.get(id=1)
expected_object_name = f'{todo.title}'
self.assertEquals(expected_object_name, 'first todo')
def test_body_content(self):
todo = Todo.objects.get(id=1)
expected_object_name = f'{todo.body}'
self.assertEquals(expected_object_name, 'a body here')
复制代码
它使用 Django 的内置 TestCase 类。首先,咱们在 setUpTestData 中设置数据,而后编写两个新测试。而后使用 python manage.py test 命令运行测试。
(backend) $ python manage.py test
…
Ran 2 tests in 0.002s
OK
复制代码
就是这样!咱们的后端现已实现。确保服务器正在运行,因为咱们将在下一章中使用它。
(backend) $ python manage.py runserver
复制代码
总结
在本文中,咱们可能看到只需起码的代码,Django REST Framework 便容许咱们从头开始创建 Django API。咱们从典型 Django 开发需要的唯一组件是 models.py 文件和 urls.py 路由。views.py 和 serializers.py 文件残缺是 Django REST Framework 特有的。
与上一示例不同,咱们没有为该我的项目构建任何网页,因为咱们的目标只是创建一个 API。然而,在将来的任何时候,咱们都可能轻松实现!只需增加一个新视图,URL 和一个模板即可公开咱们现有的数据库模型。
在此示例中,重要的一点是咱们增加了 CORS 标头,并且仅将域 localhost:3000 和 localhost:8000 明确设置为可能拜访咱们的 API。第一次开始构建 API 时,很容易混淆正确设置 CORS 标头。
咱们可能做更多的配置,当前再做,但最终,创建 Django API 的过程是建立模型,编写一些 URL 路由,而后增加 Django REST Framework 的序列化程序和视图所提供的一些魔术。