Appearance
ModelSerializer
上一章我们借助 DRF 库,写了一个简单的序列化器:
python
class ArticleListSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(allow_blank=True, max_length=100)
body = serializers.CharField(allow_blank=True)
created = serializers.DateTimeField()
updated = serializers.DateTimeField()
这个序列化器长得跟 Form
或者 Model
也太像了,甚至感觉代码都重复了。如果能再简化一下就更好了。DRF 也考虑到了这一点,提供了现成的解决方案,也就是 ModelSerializer
了。
将序列化器修改为下面这样:
python
# article/serializers.py
from rest_framework import serializers
from article.models import Article
# 父类变成了 ModelSerializer
class ArticleListSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = [
'id',
'title',
'created',
]
ModelSerializer
的功能与上一章的 Serializer
基本一致,不同的是它额外做了些工作:
- 自动推断需要序列化的字段及类型
- 提供对字段数据的验证器的默认实现
- 提供了修改数据需要用到的
.create()
、.update()
方法的默认实现
另外我们还可以在 fileds
列表里挑选出需要的数据,以便减小数据的体积。
在浏览器中访问 http://127.0.0.1:8000/api/article/
,页面中呈现的数据如下(略微排版后):
python
[
{
"created": "2020-06-15T09:24:18Z",
"id": 1,
"title": "My first post"
},
{
"created": "2020-06-15T09:24:38Z",
"id": 2,
"title": "Another post"
},
{
"created": "2020-06-15T09:24:58Z",
"id": 3,
"title": "Third article with awesome things"
}
]
可以看到 Json 数据仅包含 fields
中规定的字段了。
APIView
除了对序列化器的支持以外,DRF 还提供了对视图的扩展,以便视图更好的为接口服务。
将文章的视图修改为如下:
python
# article/views.py
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
...
@api_view(['GET', 'POST'])
def article_list(request):
if request.method == 'GET':
articles = Article.objects.all()
serializer = ArticleListSerializer(articles, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ArticleListSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
主要的变化如下:
@api_view
装饰器允许视图接收GET
、POST
请求,以及提供如405 Method Not Allowed
等默认实现,以便在不同的请求下进行正确的响应。- 返回了
Response
,该对象由 Django 原生响应体扩展而来,它可以根据内容协商来确定返回给客户端的正确内容类型。如果数据验证有误,还可以返回适当的状态码以表示当前的情况。
让我们刷新文章列表接口:
出现了可视化的接口界面!不是说好接口只返回数据吗,这是在搞毛?
这就是视图中 Response
提供的内容协商能力了。也就是说,Django 后端根据客户端请求响应的内容类型不同,自动选择适合的表现形式;浏览器请求资源时,就返回可视化的 HTML 资源表示,其他形式请求时,又可以返回 Json 纯数据的形式。这给开发带来极大的方便。
有同学就问了,那我怎么验证它是不是真的会返回 Json 数据呢?让我们发一个网络请求试试看。
在命令行中发送请求,笔者推荐 httpie 这个库,基于 Python 并且小巧美观。
重新打开一个命令行,安装方式就是万能的 pip
:
httpie 可以安装在全局。
bash
pip install httpie
安装成功后,试试在命令行提交一个请求:
python
C:\...> http http://127.0.0.1:8000/api/article/
# 以下为返回内容
HTTP/1.1 200 OK
Content-Length: 235
Content-Type: application/json
...
[
{
"created": "2020-06-15T09:24:18Z",
"id": 1,
"title": "My first post"
},
{
"created": "2020-06-15T09:24:38Z",
"id": 2,
"title": "Another post"
},
{
"created": "2020-06-15T09:24:58Z",
"id": 3,
"title": "Third article with awesome things"
}
]
再试试新建文章:
python
C:\...> http POST http://127.0.0.1:8000/api/article/ title=PostByJson body=HelloWorld!
# 以下为返回内容
HTTP/1.1 201 Created
...
{
"created": "2020-06-29T07:47:53.984916Z",
"id": 4,
"title": "PostByJson"
}
浏览文章列表、新建文章接口就完成了。
注意事项
教程为了简洁,后续发送 web 请求会采用 httpie 为主、可视化页面为辅的方式进行开发测试。
但是使用 httpie 需要一定的学习成本(并且在 Windows 命令行下有符号兼容的坑),因此本教程的读者更推荐使用 Postman,可视化界面,会点鼠标就会用,很方便。
使用 Postman 时要注意,在 Json 中单双引号含义是不同的,不要混用。
如果你确实要用 httpie,那么Windows用户注意:由于 Windows 系统旧的 Terminal
命令行与 httpie
的各种兼容问题,后续文章中凡是提到 httpie
发送请求所指的命令行,均是指 PowerShell
命令行。