泽恩小站-教程区 Help

序列化器与视图函数

ModelSerializer

上一章我们借助 DRF 库,写了一个简单的序列化器:

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 了。

将序列化器修改为下面这样:

# 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/ ,页面中呈现的数据如下(略微排版后):

[ { "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 还提供了对视图的扩展,以便视图更好的为接口服务。

将文章的视图修改为如下:

# 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 装饰器允许视图接收 GETPOST 请求,以及提供如 405 Method Not Allowed 等默认实现,以便在不同的请求下进行正确的响应。

  • 返回了 Response ,该对象由 Django 原生响应体扩展而来,它可以根据内容协商来确定返回给客户端的正确内容类型。如果数据验证有误,还可以返回适当的状态码以表示当前的情况。

让我们刷新文章列表接口:

Drf 1

出现了可视化的接口界面!不是说好接口只返回数据吗,这是在搞毛?

这就是视图中 Response 提供的内容协商能力了。也就是说,Django 后端根据客户端请求响应的内容类型不同,自动选择适合的表现形式;浏览器请求资源时,就返回可视化的 HTML 资源表示,其他形式请求时,又可以返回 Json 纯数据的形式。这给开发带来极大的方便。

有同学就问了,那我怎么验证它是不是真的会返回 Json 数据呢?让我们发一个网络请求试试看。

在命令行中发送请求,笔者推荐 httpie 这个库,基于 Python 并且小巧美观。

重新打开一个命令行,安装方式就是万能的 pip

pip install httpie

安装成功后,试试在命令行提交一个请求:

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" } ]

再试试新建文章:

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 ,可视化界面,会点鼠标就会用,很方便。

如果你确实要用 httpie,那么Windows用户注意 :由于 Windows 系统旧的 Terminal 命令行与 httpie 的各种兼容问题,后续文章中凡是提到 httpie 发送请求所指的命令行,均是指 PowerShell 命令行。

Last modified: 06 January 2025