持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 13 天,点击查看活动详情
引言
Django REST Framework 与 Django Web 框架协同工作以创建 Web API。 我们不能仅使用 Django Rest Framework 来构建 Web API 。 在安装和配置 Django 本身之后,必须始终将其添加到项目中。
在本章中,我们将回顾传统 Django 和 Django REST Framework 之间的异同。 最重要的一点是,Django 创建的网站包含网页,而 Django REST Framework 创建的 Web API 是 URL 端点的集合,这些 URL 端点包含返回 JSON 的可用 HTTP 动词。
为了说明这些概念,我们将使用传统的 Django 建立一个基本的 Library 网站,然后使用 Django REST Framework 将其扩展为 Web API 。
Django 快速开发
首先,我们需要在计算机上有一个专用目录来存储代码。 它可以放置在任何地方,但为了方便起见,如果您使用的是 Mac,我们可以将其放在“桌面”文件夹中。
$ cd ~/Desktop
$ mkdir code && cd code
该代码文件夹将成为本书所有代码的位置。 下一步是为我们的库站点创建一个专用目录,通过 Pipenv 安装 Django ,然后使用 shell 命令进入虚拟环境。 您应该始终为每个新的 Python 项目使用专用的虚拟环境。
$ mkdir library && cd library
$ pipenv install django==2.2.6
$ pipenv shell
(library) $
Pipenv 在当前目录中创建一个 Pipfile 和一个 Pipfile.lock 。 命令行前括号中的(library)表明我们的虚拟环境处于活动状态。
传统的 Django 网站由一个项目 project 和一个(或多个)代表不同功能的应用 apps 组成。 让我们使用 startproject 命令创建一个新项目。 别忘了加上句号。 最后将代码安装在当前目录中。 如果不包括句点,则 Django 默认会创建一个附加目录。
(library)$ django-admin startproject library_project .
Django 会自动为我们生成一个新项目,我们可以使用 tree 命令看到它。 (注意:如果在 Mac 上无法使用 tree ,请使用 Homebrew :brew install tree 安装。)
(library) $ tree .
├── Pipfile
├── Pipfile.lock
├── library_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
这些文件具有以下定义:
__init__.py是将目录视为软件包的 Python 方法; 它是空的settings.py包含我们项目的所有配置urls.py控制顶级 URL 路由wsgi.py代表 Web 服务器网关界面,可帮助 Django 服务于最终网页manage.py执行各种Django 命令,例如运行本地 Web 服务器或创建新应用。
运行 migrate 将数据库与 Django 的默认设置同步,然后启动本地 Django Web 服务器。
(library) $ python manage.py migrate
(library) $ python manage.py runserver
打开Web浏览器,访问 http://127.0.0.1:8000/ 以确认我们的项目已成功安装。
第一个app
典型的下一步是开始添加代表功能不同区域的应用程序。 一个 Django 项目可以支持多个应用程序。
通过键入 Control + c 停止本地服务器,然后创建一个 books 应用程序。
(library) $ python manage.py startapp books
现在再查看一下 Django 生成了什么文件。
.
├── Pipfile
├── Pipfile.lock
├── books
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── library_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
每个应用程序都有一个 __init__.py 文件,将其标识为 Python 软件包。 创建了 6 个新文件:
admin.py是内置 Django Admin 应用程序的配置文件apps.py是应用程序本身的配置文件migrations/目录存储用于数据库更改的迁移文件models.py是我们定义数据库模型的地方tests.py用于我们的应用程序特定测试views.py是我们处理 Web 应用程序的请求/响应逻辑的地方
通常,开发人员还会在每个应用程序内创建一个 urls.py 文件进行路由。
让我们构建文件,以便我们的图书馆项目列出首页上的所有书籍。 将您选择的文本编辑器打开到 settings.py 文件。 第一步是将新应用添加到我们的 INSTALLED_APPS 配置中。 我们总是在底部添加新应用,因为 Django 会按顺序读取它们,并且我们希望内置的核心 Django 应用(例如 admin 和 auth )在加载我们的应用之前已经被加载。
# library_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Local
'books.apps.BooksConfig', # new
]
然后运行迁移以使我们的数据库与更改同步。
(library) $ python manage.py migrate
传统 Django 中的每个网页都需要多个文件:视图,URL 和模板。 但是首先我们需要一个数据库模型,所以让我们从这里开始。
Models
在您的文本编辑器中,打开文件 book/models.py 并进行如下更新:
# books/models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=250)
subtitle = models.CharField(max_length=250)
author = models.CharField(max_length=100)
isbn = models.CharField(max_length=13)
def __str__(self):
return self.title
这是一个基本的 Django 模型,我们在最上面一行从 Django 导入模型,然后创建一个扩展它的 Book 类。 有四个字段:标题,副标题,作者和 isbn 。 我们还包括 __str__ 方法,以便稍后在管理员中显示书名。
请注意,ISBN 是分配给每本出版书籍的唯一的 13 个字符的标识符。
由于我们创建了一个新的数据库模型,因此我们需要创建一个迁移文件来进行处理。 指定应用名称是可选的,但建议在此处使用。 我们可以只键入 python manage.py makemigrations,但是如果有多个应用程序进行了数据库更改,那么这两个应用程序都将被添加到迁移文件中,这使得将来的调试更加困难。 保持您的迁移文件尽可能具体。
然后运行迁移以更新我们的数据库。
(library) $ python manage.py makemigrations books
(library) $ python manage.py migrate
到目前为止,一切都很好。
Admin
我们可以开始通过内置的 Django 应用将数据输入到我们的新模型中。 但是我们必须首先做两件事:
创建一个超级用户帐户并更新 admin.py ,以便显示 books 应用程序。从超级用户帐户开始。 在命令行上运行以下命令:
(library) $ python manage.py createsuperuser
按照提示输入用户名,电子邮件和密码。 请注意,出于安全原因,输入密码时屏幕上不会显示文本。
现在更新我们的图书应用的 admin.py 文件。
# books/admin.py
from django.contrib import admin
from .models import Book
admin.site.register(Book)
这就是我们所需要的! 再次启动本地服务器。
(library) $ python manage.py runserver
导航到 http://127.0.0.1:8000/admin 并登录。
您将被重定向到管理员主页。
单击书籍的链接。
然后点击右上角的“添加图书+”按钮。
我已经输入了 Django 初学者书籍的详细信息。 您可以在此处输入任何文本。 纯粹是出于演示目的。 单击“保存”按钮后,我们将重定向到列出所有当前条目的“书籍”页面。
我们传统的 Django 项目现在有数据,但是我们需要一种将其公开为网页的方法。 这意味着创建视图,URL和模板文件。 现在开始吧。
Views
views.py 文件控制如何显示数据库模型内容。 由于我们要列出所有书籍,因此可以使用内置的通用类 ListView。更新 books/views.py 文件。
# books/views.py
from django.views.generic import ListView
from .models import Book
class BookListView(ListView):
model = Book
template_name = 'book_list.html'
首先,我们导入了 ListView 和 Book 模型。 然后,我们创建一个 BookListView 类,该类指定要使用的模型和模板(尚未创建)。
在拥有一个正常工作的网页之前,需要执行两个步骤:制作模板并配置 URL 。 让我们从 URL 开始。
URLs
我们需要同时设置项目级别的 urls.py 文件,然后在 books 应用程序中设置一个。 用户访问我们的网站时,他们将首先与 library_project/urls.py文件进行交互,因此,请先对其进行配置。
# library_project/urls.py
from django.contrib import admin
from django.urls import path, include # new
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('books.urls')), # new
]
前两行会导入内置的管理应用程序,路线的路径,并包括将与我们的图书应用程序一起使用的内容。 如果用户转到 /admin/,他们将被重定向到 admin 应用。 我们在图书应用路由中使用空字符串 ' ',这意味着首页上的用户将直接重定向到图书应用。
现在,我们可以配置我们的 books/urls.py 文件。 但是,糟糕! Django由于某种原因在应用程序中默认不包含 urls.py 文件,因此我们需要自己创建它。
(library) $ touch books/urls.py
现在,在文本编辑器中更新新文件。
# books/urls.py
from django.urls import path
from .views import BookListView
urlpatterns = [
path('', BookListView.as_view(), name='home'),
]
我们导入视图文件,在空字符串''处配置 BookListView ,并添加命名 URL 主页作为最佳实践。
Django 的工作方式,现在,当用户转到我们网站的主页时,他们将首先点击 library_project/urls.py 文件,然后将其重定向到使用 BookListView 指定的 books/urls.py。 在此视图文件中,Book 模型与 ListView 一起使用以列出所有书籍。
最后一步是创建我们的模板文件,以控制实际网页上的布局。 我们已经在视图中将其名称指定为book_list.html。 其位置有两个选项:默认情况下,Django 模板加载器将在以下位置的 books 应用程序内查找模板:books/templates/books/book_list.html。 我们也可以改为创建一个单独的项目级模板目录,然后更新 settings.py 文件以指向该目录。
首先在 books 应用中创建一个新的模板文件夹,然后在其中创建一个 books 文件夹,最后是一个book_list.html 文件。
(library) $ mkdir books/templates
(library) $ mkdir books/templates/books
(library) $ touch books/templates/books/book_list.html
然后更新 template 文件,
<!-- books/templates/books/book_list.html -->
<h1>All books</h1>
{% for book in object_list %}
<ul>
<li>Title: {{ book.title }}</li>
<li>Subtitle: {{ book.subtitle }}</li>
<li>Author: {{ book.author }}</li>
<li>ISBN: {{ book.isbn }}</li>
</ul>
{% endfor %}
Django 内置了允许基本逻辑的模板语言。 在这里,我们使用 for 标签来遍历所有可用的书。 模板标签必须包含在左/右括号和括号内。 因此,格式始终为{%for ...%},然后我们必须稍后使用{%endfor%}关闭循环。
我们要遍历的是对象,其中包含 ListView 提供的所有可用书籍。 该对象的名称为 object_list 。 因此,为了遍历每本书,我们在{% for book in object_list %}。 然后显示模型中的每个字段。
网页
现在,我们可以启动本地 Django 服务器并查看我们的网页。
(library) $ python manage.py runserver
导航至位于 http://127.0.0.1:8000/ 的主页。
如果我们在管理员中添加其他图书,则它们也都将出现在此处。
这是对传统 Django 网站的快速浏览。 现在,向其中添加一个 API !
Django REST 框架
就像其他任何第三方应用程序一样,添加了 Django REST Framework。 如果本地服务器 Control + c 仍在运行,请确保退出它。 然后在命令行上键入以下内容。
(library) $ pipenv install djangorestframework==3.10.3
在我们的 settings.py 文件中,将 rest_framework 添加到 INSTALLED_APPS 配置中。 我喜欢在第三方应用程序和本地应用程序之间做出如下区分,因为在大多数项目中,应用程序的数量迅速增长。
最终,我们的 API 将公开一个端点,该端点列出 JSON 中的所有书籍。 因此,我们将需要一个新的URL路由,一个新的视图以及一个新的序列化器文件(稍后将对此进行更多介绍)。
我们可以用多种方法来组织这些文件,但是我的首选方法是创建一个专用的 api 应用程序。 这样,即使将来我们增加更多应用程序,每个应用程序都可以包含专用网页所需的模型,视图,模板和 url,但是整个项目的所有 API 专用文件都将驻留在专用 api 应用程序中。
让我们新建一个 api 应用程序。
(library) $ python manage.py startapp api
然后增加到 INSTALLED_APPS
# library_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',
# Local Apps
'books.apps.BooksConfig',
'api.apps.ApiConfig', # new
]
api 应用程序将没有自己的数据库模型,因此无需像通常那样创建迁移文件和更新数据库。
URLs
从 URL 配置开始。 添加 API 端点就像配置传统 Django 应用的路由一样。 首先,在项目级别,我们需要包括 api 应用程序并配置其 URL 路由,即 api/。
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('books.urls')),
path('api/', include('api.urls')), # new
]
然后在api应用程序中创建 urls.py 文件。
(library) $ touch api/urls.py
然后更新这个文件,如下:
# api/urls.py
from django.urls import path
from .views import BookAPIView
urlpatterns = [
path('', BookAPIView.as_view()),
]
一切准备就绪。
Views
接下来是我们的 views.py 文件,该文件依赖 Django REST Framework 的内置通用类视图。 这些是故意模仿传统 Django 基于类的通用视图的格式,但它们不是一回事。
为避免混淆,某些开发人员将调用 API 视图文件 apiviews.py 或 api.py。 就个人而言,在专用的 api应用程序中工作时,我发现仅调用 Django REST 框架视图文件 views.py 并不会造成混淆,但是在这一点上意见不一。
在我们的 views.py 文件中,将其更新为如下所示:
# api/views.py
from rest_framework import generics
from books.models import Book
from .serializers import BookSerializer
class BookAPIView(generics.ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
在最上面的几行中,我们导入 Django REST Framework 的通用类视图,我们的 Books 应用中的模型以及 api 应用中的序列化器(我们将在下一个序列化器中导入)。
然后,我们创建一个 BookAPIView ,它使用 ListAPIView 为所有书籍实例创建一个只读端点。 有许多通用的视图,我们将在后面的章节中进一步探讨它们。
在我们的视图中,仅需执行两个步骤,即指定所有可用书籍的 queryset ,然后指定将成为 BookSerializer的 serializer_class。
Serializers
序列化器将数据转换为易于在 Internet 上使用的格式(通常为 JSON ),并显示在 API 端点上。 在接下来的章节中,我们还将更深入地介绍序列化器和 JSON 。 现在,我想演示使用 Django REST Framework创建序列化器以将 Django 模型转换为 JSON 是多么容易。
在 api 应用中创建一个 serializers.py 文件:
(library) $ touch api/serializers.py
然后在文本编辑器中更新为如下所示:
# api/serializers.py
from rest_framework import serializers
from books.models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ('title', 'subtitle', 'author', 'isbn')
首先,我们从 Books 应用程序中导入 Django REST Framework 的序列化器类和 Book 模型。 我们将 Django REST Framework 的 ModelSerializer 扩展到 BookSerializer 类中,该类指定我们的数据库模型 Book 和我们希望公开的数据库字段:标题,副标题,作者和 isbn 。
大概就是这样! 完成了
cURL
我们想看看我们的 API 端点是什么样子。 我们知道它应该在URL http://127.0.0.1:8000/api/ 返回 JSON 。 确保我们的本地 Django 服务器正在运行:
(library) $ python manage.py runserver
现在打开一个新的第二个命令行控制台。 我们将使用它来访问在现有命令行控制台中运行的 API。
我们可以使用流行的 cURL 程序通过命令行执行 HTTP 请求。 我们需要一个基本的 GET 请求,以指定curl和我们要调用的 URL。
$ curl http://127.0.0.1:8000/api/
[ { "title":"Django for Beginners", "subtitle":"Build websites with Python and Django", "author":"William S. Vincent", "isbn":"978-198317266" } ]
数据全部以 JSON 格式存在,但格式不正确且难以理解。 幸运的是,Django REST Framework 给我们带来了另一个惊喜:API端点的强大可视模式。
Browsable API
在本地服务器仍在第一个命令行控制台中运行的情况下,在 Web 浏览器中的 http://127.0.0.1:8000/api/上导航到我们的API端点。
Django REST Framework 默认情况下提供此可视化。 此页面中内置了许多功能,我们将在整本书中进行探讨。 现在,我希望您将此页面与原始JSON端点进行比较。 单击“获取”按钮,然后从下拉菜单中选择“ json”。
这就是来自API端点的原始 JSON 的样子。 我认为我们可以同意 Django REST Framework 版本更具吸引力。
总结
在本章中,我们创建了一个传统的 Django 图书馆网站。 然后,我们添加了 Django REST Framework ,并能够以最少的代码添加 API 端点。