Django REST框架初学者指南
因此,您正在学习使用Django Web框架,并且您很喜欢它。但是,您想要一个吸引人的、易于使用的API用于您的应用程序吗?只需看一看Django REST框架(DRF)。DRF是强大的,复杂的,令人惊讶的易于使用。它提供了一个吸引人的Web浏览器版本的API,以及返回原始JSON的选项。Django REST Framework提供强大的模型序列化,使用基于标准函数的视图显示数据,或者为更复杂的功能提供基于类的强大视图的粒度。所有这些都是完全符合REST的包装器。我们开始吧。
奠定基础
在使用Python应用程序时,最好用虚拟环境为您的开发添加沙箱。它有助于防止应用程序中所需的库与计算机上可能已经安装的库之间的版本冲突,使在虚拟env使用requirements.txt
文件,最后,它使得与其他开发人员共享您的开发环境非常简单。
TUTS+有两个关于如何安装的优秀视频虚拟人和虚拟包装器...花几分钟时间浏览一下这些视频,以便在您的计算机上安装Virtualenv和Virtualenvrapper。如果您已经安装了它们,那么跳过下一节。
建立虚拟环境
作为应用程序的一部分,我们要做的第一件事是设置虚拟环境。在终端中输入以下命令。
|
1
2
|
$ mkvirtualenv drf
$ workon drf
|
当这些命令运行时,您在文件系统中的位置并不重要。所有Viralenv文件都存储在一个集中的位置,并按需激活。
广告
安装Django应用程序
由于本文并不是关于Django本身的,所以我创建了一个包含我们将要使用的应用程序的存储库,从而节省了一些时间。这是一个简单的书架应用程序,它允许我们存储作者和书籍的列表。下载本文的配套存储库,进入您选择的目录,然后运行pip install -r requirements.txt
若要安装所有依赖项,请执行以下操作。请记住,您已经激活了我们在最后一步中设置的虚拟环境。安装完成后,您应该能够键入fab runserver
启动本地web服务器并打开指向http://127.0.0.1:8000/
...如果你在屏幕上看到一张作者名单,那你就可以走了。
如果在任何时候没有得到预期的结果,请尝试将本地存储库的分支切换到Final,以查看结果:git checkout final
.
法布?那是什么?
法布==织物..Python任务运行程序...从医生那里:
Fabric是Python(2.5或更高版本)库和命令行工具,用于简化应用程序部署或系统管理任务中SSH的使用。
虽然关于Fabric的更完整的讨论超出了本文的范围,但我已经实现了一些基本的fab命令,这些命令使得使用这个应用程序更加容易。你见过fab runserver
命令。还有fab shell
命令,它在应用程序的上下文中打开交互式IPython shell,并在fab syncdb
命令运行Django的syncdb
命令将模型中的更改同步到数据库。
使用序列化
Django REST框架的一个强大特性是它提供的内置模型序列化。只需几行代码,您就可以对可以以多种格式传递的数据组成强大的表示形式。如前所述,我们的应用程序将是一个简单的书架应用程序,包含作者和书籍。我已经创建了Author
和Book
为你做模特,所以敞开心扉/app/bookreview/models.py
...本地SQLite数据库中已经存储了一些作者,所以让我们为我们的应用程序打开一个交互式的shell,然后四处查看。切换到终端窗口,确保您在./app
目录并键入以下命令。
|
1
|
$ fab shell
|
在shell加载之后,输入接下来的几行,从数据库中检索一个作者记录,这恰好是我的。真巧合。*)
|
1
2
3
4
5
6
7
8
|
$ from bookreview.models ``import
Author
$ author = Author.objects.get(pk=1)
$ author.``id
> 1
$ author.first_name
> u``'Andy'
$ author.last_name
> u``'Matthews'
|
类似地,您可以使用不同的命令从数据库检索所有的Author记录:
|
1
2
3
4
|
$ from bookreview.models ``import
Author
$ authors = Author.objects.all()
$ authors
> [<Author: Andy Matthews>, <Author: China Mieville>, <Author: Neil Gaiman>, <Author: Veronica Roth>, <Author: Suzanne Collins>, <Author: Brandon Sanderson>, <Author: Rick Riordan>, <Author: Phillip K. Dick>, <Author: John Scalzi>, <Author: Jesse Petersen>]
|
不幸的是,这并不返回Ajax调用能够理解的数据。因此,让我们为作者添加一个序列化程序。通过键入关闭外壳quit
敞开心扉bookreview/serializers.py
...键入或粘贴下几行代码并保存该文件。
|
1
2
3
4
5
6
7
|
class
AuthorSerializer(serializers.ModelSerializer):
"""
Serializing all the Authors
"""
class
Meta:
model ``=
Author
fields ``=
(``'id'``, ``'first_name'``,``'last_name'``)
|
没有做任何进一步的改变,序列化程序给了我们相当大的力量。回到壳里,让我们回顾一下。
|
1
2
3
4
5
6
|
$ from bookreview.models ``import
Author
$ from bookreview.serializers ``import``AuthorSerializer
$ author = Author.objects.get(pk=1)
$ serialized = AuthorSerializer(author)
$ serialized.data
> {``'id'``: 1, ``'first_name'``: u``'Andy'``, ``'last_name'``: u``'Matthews'``}
|
让我们再添加几行代码,看看我们的API将在新的数据运行后在浏览器中显示什么AuthorSerializer
.
查看Web可浏览API
第一,打开bookreview/urls.py
并将下面的行添加到index_view
路线:
|
1
|
url(r``'^authors/$'``, views.AuthorView.as_view(), name``=``'author-list'``),
|
接下来,打开bookreview/views.py
并将这些行添加到文件的末尾:
|
1
2
3
4
5
6
|
class
AuthorView(generics.ListAPIView):
"""
Returns a list of all authors.
"""
model ``=
Author
serializer_class ``=
AuthorSerializer
|
然后确保为AuthorSerializer
在页面顶部:
|
1
|
from
bookreview.serializers ``import
AuthorSerializer
|
Django REST Framework的默认视图是APIView。它允许您定义自己的get
, put
,和delete
方法。这是获得基本功能的好方法,但仍然可以控制最终结果。但是,在我们的例子中,我们通过扩展ListAPIView让DRF为我们完成繁重的工作。我们只需要提供一些信息就可以让DRF连接到各个部分。我们给它Author
模型,以便它知道如何与数据库进行对话,以及AuthorSerializer
以便DRF知道如何返回信息。我们将只使用几个内置的APIViews,但您可以阅读所有选项在Django REST框架网站上。
现在您已经做了这些更改,请通过键入fab runserver
然后输入URLhttp://127.0.0.1:8000/authors/
...您应该会看到一个设计精美的API视图页面,其中包含数据库中所有作者的列表。
现在我们已经准备好了AuthorsAPI视图,尝试使用curl
指挥:
|
1
2
|
$ curl http:``//127``.0.0.1:8000``/authors/
> [{``"id"``: 1, ``"first_name"``: ``"Andy"``, ``"last_name"``:``"Matthews"``},..., {``"id"``: 10, ``"first_name"``: ``"Jesse"``,``"last_name"``: ``"Petersen"``}]
|
很时髦吧?
给作者一些书!
虽然这个API视图非常流畅,但它与数据库是一对一的。让我们通过为作者构建一个更复杂的数据集来启动我们的API视图,包括他们所有书籍的列表。打开bookreview/serializers.py
之前添加以下代码行AuthorSerializer
类定义。
|
1
2
3
4
5
6
7
|
class
BookSerializer(serializers.ModelSerializer):
"""
Serializing all the Books
"""
class
Meta:
model ``=
Book
fields ``=
(``'id'``, ``'title'``, ``'isbn'``)
|
之前,我们可以将书籍添加到AuthorSerializer
我们得把书连载起来。这对你来说应该很熟悉。因为它几乎与AuthorSerializer
我们不打算讨论这个问题。
接下来,在AuthorSerializer
班级:
|
1
|
books ``=
BookSerializer(many``=``True``)
|
然后添加books
类的内部元类的字段属性。AuthorSerializer
:
|
1
|
fields ``=
(``'id'``, ``'first_name'``, ``'last_name'``, ``'books'``)
|
重新加载/authors/
端点,现在您应该可以看到每个作者都有一系列的书籍。再多几行代码还不错吧?
真不错,DRF!
使用SerializerMethod字段创建自定义属性
序列化程序很聪明.当我们指出它应该在内部元类中序列化哪个模型时,它知道关于该模型的一切.属性、长度、默认值等等。注意,我们没有直接在序列化器中定义在模型上找到的任何属性,我们只是指示应该将哪些字段返回给fields
财产。
因为DRF已经知道了模型的特性,所以它不需要我们重复。如果我们愿意,我们可以在BookSerializer
再加上以下几行.DRF也会很高兴的。
|
1
2
|
title ``=
serializers.Field(source``=``'title'``)
isbn ``=
serializers.Field(source``=``'isbn'``)
|
这个serializers.field
方法允许指向模型的现有属性,即source
字段,并允许您在将其返回给最终用户时显式地命名它。但是关于serializers.SerializerMethodField
?这允许您创建一个自定义属性,该属性不直接绑定到模型,其内容是方法调用的结果。在我们的例子中,我们将返回一个URL,其中包含一个你可以去购买这本书的地方的列表。现在让我们添加自定义方法。
控件的docstring之后。BookSerializer
添加以下字符串:
|
1
|
search_url ``=``serializers.SerializerMethodField(``'get_search_url'``)
|
然后在class Meta
的定义BookSerializer
增加以下几行:
|
1
2
|
def
get_search_url(``self``, obj):
return``"[http://www.isbnsearch.org/isbn/](http://www.isbnsearch.org/isbn/){}"``.``format``(obj.isbn)
|
最后,我们需要将我们的新属性添加到字段列表中。改变这一点:
|
1
|
fields ``=
(``'id'``, ``'title'``, ``'isbn'``)
|
对此:
|
1
|
fields ``=
(``'id'``, ``'title'``, ``'isbn'``, ``'search_url'``)
|
重新加载/authors/
端点,现在您应该会看到一个URL与有关该书的其他信息一起返回。
添加作者终结点
我们已经有了一个作者列表,但是每个作者都有他们自己的页面,就像MySpace一样,对吧?让我们添加一个API端点来查看单个作者。打开urls.py
并在author-list
路线:
|
1
|
url(r``'^authors/(?P<pk>[\d]+)/$'``, views.AuthorInstanceView.as_view(), name``=``'author-instance'``),
|
然后打开views.py
之后添加以下行AuthorView
班级:
|
1
2
3
4
5
6
7
|
class
AuthorInstanceView(generics.RetrieveAPIView):
"""
Returns a single author.
Also allows updating and deleting
"""
model ``=
Author
serializer_class ``=
AuthorSerializer
|
单击索引页上的某个作者名称,您将看到Author实例页面加载。
为胜利而重构!
现在是快速重构的好时机。因为Django提供了命名路由的选项,所以我们可以使用该名称引用路由。这使我们不必手动构建URL。打开templates/index.html
并交换以下部分:
|
1
|
<``a
href``=``"/authors/{{author.id}}/"``>{{author.first_name}} {{author.last_name}}</``a``>
|
用这条线
|
1
|
<``a
href``=``"{% url 'author-instance' author.id %}"``>{{author.first_name}} {{author.last_name}}</``a``>
|
保存数据:让DRF为您工作!
到目前为止,我们的应用程序一直是只读的。是时候开始保存一些数据了。打开templates/index.html
并在作者标题下面添加以下行:
|
1
2
3
4
5
|
<``form
action``=``"{% url 'author-list' %}"``method``=``"post"``>
<``input
type``=``"text"
name``=``"first_name"
/>
<``input
type``=``"text"
name``=``"last_name"
/>
<``input
type``=``"submit"
value``=``"Add Author"
/>
</``form``>
|
DRF没那么神奇.或者是吗?
打开views.py
,更改AuthorView
从generics.ListAPIView
到generics.ListCreateAPIView
...然后再试一次你的请求。砰!你是个作家!你四年级的体育老师说你什么都没有。但他所知道的是,他整天都在汗流浃背的袜子里工作。回到主作者的页面,在灯光中看到你的名字。
刚刚发生了什么?我们使用的默认API视图仅允许GET
对作者端点的请求。通过将其更改为ListCreateAPIView,我们告诉DRF我们也希望允许POST
请求。它为我们做了一切。我们也可以很容易地定义我们自己的post
方法中的AuthorView
在那里做些额外的事情。看起来可能是这样的:
|
1
2
|
def
post(``self``, ``*``args, ``*``*``kwargs):
import
pdb; pdb.set_trace()
|
请记住,虽然DRF确实基于模型的属性强制执行数据库完整性,但我们并不对可以访问或使用此表单的人设置任何类型的安全性。深入研究安全性、登录和管理权限超出了本文的范围,但只需说一句就够了。DRF确实有功能允许访问您已经使用过的视图,设置起来非常简单。
完成
您现在已经了解了很多关于Django REST框架的知识:如何实现可以为您返回JSON的web视图API,如何配置序列化器来组合和转换数据,以及如何使用基于类的视图来抽象样板代码。
DRF比我们能够覆盖的几个位还多,但我希望您会发现它对您的下一个应用程序有用。
网友评论