别院牧志知识库 别院牧志知识库
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2025 面试记录
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
首页
  • 基础

    • 全栈之路
    • 😎Awesome资源
  • 进阶

    • Python 工匠系列
    • 高阶知识点
  • 指南教程

    • Socket 编程
    • 异步编程
    • PEP 系列
  • 面试

    • Python 面试题
    • 2025 面试记录
    • 2022 面试记录
    • 2021 面试记录
    • 2020 面试记录
    • 2019 面试记录
    • 数据库索引原理
  • 基金

    • 基金知识
    • 基金经理
  • 细读经典

    • 德隆-三个知道
    • 孔曼子-摊大饼理论
    • 配置者说-躺赢之路
    • 资水-建立自己的投资体系
    • 反脆弱
  • Git 参考手册
  • 提问的智慧
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 辨析

  • Sockets编程

  • Django

    • Django 学习资料收集
    • Django-REST-framework教程中文版

      • Django-REST-framework 教程中文版
      • 快速入门
      • 教程 1:序列化
      • 教程 2:Requests 和 Responses
        • Request 对象
        • Response 对象
        • 状态码
        • 装饰 API 视图
        • 协同工作
        • 为 URL 添加可选的数据格式后缀
        • 测试
        • 易读性
        • 接下来
      • 教程 3:类视图
      • 教程 4:认证和权限
      • 教程 5:Relationships 和 Hyperlinked
      • 教程 6:ViewSets 和 Routers
  • stackoverflow

  • Flask

  • 全栈之路

  • 面试

  • 代码片段

  • 异步编程

  • 😎Awesome资源

  • PEP

  • Python工匠系列

  • 高阶知识点

  • Python 学习资源待整理
  • 设计模式

  • 好“艹蛋”的 Python 呀!
  • FIFO | 待学清单📝
  • pip 安装及使用
  • 数据分析

  • 源码阅读计划

  • OOP

  • 关于 python 中的 setup.py
  • 并行分布式框架 Celery
  • 七种武器,让你的代码提高可维护性
  • 使用 pdb 调试 Python 代码
  • 每周一个 Python 标准库
  • 🐍Python
  • Django
  • Django-REST-framework教程中文版
佚名
2021-04-13
目录

教程 2:Requests 和 Responses

从本章开始,我们将开始探索框架的核心,这里先介绍一些重要的概念。

# Request 对象

REST framework 使用一个叫Requests的对象扩展了原生的HttpRequest,并提供了更灵活的请求处理。Requests对象的核心属性就是request.data,和requests.POST类似,但更强大:

request.POST  # 只处理form数据.只接受'POST'方法.
request.data  # 处理任意数据.接受'POST','PUT'和'PATCH'方法.
1
2

# Response 对象

REST framework 也提供了一个获取未渲染(unrendered)内容为TemplateResponse类型的Response对象,并使用内容协商来确定返回给客户端的正确内容类型。(原文如下,这句话我怎么翻译都觉得别扭,意思就是客户端要神码类型它返回神码类型)

REST framework also introduces a Response object, which is a type of TemplateResponse that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.

    return Response(data)  # 返回类型由发出请求的客户端决定
1

# 状态码

使用数字 HTTP 状态码并不总是易于阅读的,并且当你得到一个错误的状态码时不容易引起注意。REST framework 为每个状态码都提供了更明显的标志,比如status模块中的HTTP_400_BAD_REQUEST,使用它们替代数字是一个好注意。

# 装饰 API 视图

REST framework 提供了 2 种装饰器来编写视图:

  1. 基于函数视图的@api_view
  2. 基于类视图的APIView

这些装饰器提供了少许功能,比如确保在视图中接收Request实例,添加 context 到Resonse对象来决定返回类型。

此外还提供了适当的错误处理,比如405 Method Not Allowed、并处理在使用格式错误的输入来访问request.data时发生的任何ParseError异常。

# 协同工作

现在我们使用这些组件来改写 views.

我们不再需要JSONResponse类了,删除它后修改代码如下:

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    展示或创建snippets.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(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)  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

改造后的代码更简洁了,并且更像 Forms。也使用了命名后的状态码让 Response 含义更加明显。

接下来修改单一的 snippets 视图:

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    修改或删除一个snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

一切都是如此熟悉,这和原生的 Django Form 很像。

注意,我们并没有显式地声明 request 和 response 中的内容类型,request.data可以处理请求传入的 json 类型数据,也可以处理其他类型数据。同理,Response 对象也可以为我们返回正确的数据类型。

# 为 URL 添加可选的数据格式后缀

我们的 responses 支持多种返回格式,利用这点我们可以通过在 URL 中添加格式后缀的方法来获取单一数据类型,这意味着我们的 URL 可以处理类似http://example.com/api/items/4/.json这样的格式。

首先在 views 添加format参数:

def snippet_list(request, format=None):
    pass
1
2

和

def snippet_detail(request, pk, format=None):
    pass
1
2

然后修改urls.py,添加format_suffix_patterns:

from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    path('snippets/', views.snippet_list),
    path('snippets/<int:pk>', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)
1
2
3
4
5
6
7
8
9
10

我们不需要添加任何额外信息,它给我们一个简单清晰的方法去获取指定格式的数据。

# 测试

和上一章一样,我们使用命令行来进行测试。尽管为了更好地处理异常添加了相应的错误处理,但一切还是那么简单:

    http http://127.0.0.1:8000/snippets/
    
    HTTP/1.1 200 OK
    ...
    [
      {
        "id": 1,
        "title": "",
        "code": "foo = \"bar\"\n",
        "linenos": false,
        "language": "python",
        "style": "friendly"
      },
      {
        "id": 2,
        "title": "",
        "code": "print \"hello, world\"\n",
        "linenos": false,
        "language": "python",
        "style": "friendly"
      }
    ]
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

我们可以通过控制Accept来控制返回的数据类型:

http http://127.0.0.1:8000/snippets/ Accept:application/json  # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html         # Request HTML
1
2

或者通过添加格式后缀:

http http://127.0.0.1:8000/snippets.json  # JSON suffix
http http://127.0.0.1:8000/snippets.api   # Browsable API suffix
1
2

同样的,我们可以通过Content-Type控制发送请求的数据类型:

# POST using form data
http --form POST http://127.0.0.1:8000/snippets/ code="print 123"

{
    "id": 3,
    "title": "",
    "code": "print 123",
    "linenos": false,
    "language": "python",
    "style": "friendly"
}

# POST using JSON
http --json POST http://127.0.0.1:8000/snippets/ code="print 456"

{
    "id": 4,
    "title": "",
    "code": "print 456",
    "linenos": false,
    "language": "python",
    "style": "friendly"
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

或打开浏览器访问http://127.0.0.1:8000/snippets/

# 易读性

由于 API 根据客户端发出的请求来决定返回的数据类型,当我们使用浏览器访问时默认要求返回 HTML 数据格式,这使我们的 API 在浏览器访问时结果格式十分易读。

使用浏览器访问时返回易于阅读结果是一个巨大的进步,这让我们更容易的开发、使用 API。这使其他人员更加方便的使用、检查 API。

# 接下来

在第 3 部分中,我们将开始使用基于类的视图,并看看泛型视图如何减少我们需要编写的代码量。

编辑 (opens new window)
#DRF
上次更新: 2024-07-23, 01:00:43
教程 1:序列化
教程 3:类视图

← 教程 1:序列化 教程 3:类视图→

最近更新
01
2025 面试记录
05-28
02
提升沟通亲和力的实用策略
03-26
03
工作
07-15
更多文章>
Theme by Vdoing | Copyright © 2019-2025 IMOYAO | 别院牧志
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式