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

    • 全栈之路
    • 😎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
      • 教程 3:类视图
      • 教程 4:认证和权限
      • 教程 5:Relationships 和 Hyperlinked
        • 为 API 创建一个根 URL
        • 为语法高亮功能创建 URL
        • 使用超链接
        • 为 URL 命名
        • 分页
        • 测试
      • 教程 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
目录

教程 5:Relationships 和 Hyperlinked

目前我们使用主键来表示模型之间的关系。在本章,我们将使用超链接关系来提高 API 的内聚性以及可读性。

# 为 API 创建一个根 URL

现在我们'snippets'和'users'创建了相应的 URL,但我们的 API 没有一个统一的入口。我们使用早些介绍的普通函数视图和@api_view装饰器来创建一个,编辑snippets/views.py添加下面代码:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse


@api_view(['GET'])
def api_root(request, format=None):
    return Response({
        'users': reverse('user-list', request=request, format=format),
        'snippets': reverse('snippet-list', request=request, format=format)
    })
1
2
3
4
5
6
7
8
9
10
11

这里有两件事需要注意:首先我们使用的是 REST 框架提供的reverse函数来返回完全限定的 URL;第二,URL 通过稍后定义在snippets/urls.py中的名字来被识别。

# 为语法高亮功能创建 URL

很明显的一件事就是我们还没为语法高亮功能创建 URL。

与其它的 API 不同,这个接口我们想使用 HTML 来表示而不是 JSON。REST 框架提供了 2 种呈现 HTML 的方法,一种是使用模板渲染,另一种则是使用已经构建好的 HTML 代码。这里我们使用第二种方式。

另一个需要考虑的就是不存在通用类视图来供我们创建语法高亮视图使用,所以这里不返回一个对象实例,而是返回对象实例的属性。

这里我们使用最基础的类视图的get()方法而非通用类视图,在snippets/views.py中添加如下代码:

from rest_framework import renderers
from rest_framework.response import Response

class SnippetHighlight(generics.GenericAPIView):
    queryset = Snippet.objects.all()
    renderer_classes = (renderers.StaticHTMLRenderer,)

    def get(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)
1
2
3
4
5
6
7
8
9
10

就像往常一样,我们还需要为新的视图来创建 URL 配置。修改snippets/urls.py,添加:

path('', views.api_root),
1

同时为 snippet highlights 添加 url 匹配:

path('snippets/<int:pk>/highlight/', views.SnippetHighlight.as_view()),
1

# 使用超链接

在 Web API 中处理实体之间的关系是一件非常头疼的事情。下面有几种不同的方法来表示关系:

  • 使用主键
  • 使用超链接
  • 在相关实体间使用唯一的 slug 字段表示
  • 在相关实体间使用默认的字符串表示
  • 将相关的子实体嵌套到上级关系中
  • 其他自定义方法

REST framework 支持上述所有方法,并且可以应用于正向关系、反向关系或类似通用外键这类自定义管理项中。

在这里我们在实体间使用超链接来进行关联,为了达到这个目的我们需要修改 serializers,使用HyperlinkedModelSerializer来替代原先的ModelSerializer:

  • HyperlinkedModelSerializer 默认不包含主键
  • HyperlinkedModelSerializer 自动包含 URL 字段 HyperlinkedIdentityField
  • 使用 HyperlinkedRelatedField 来替代 PrimaryKeyRelatedField 表示关系

我们可以很容易的改写代码,编辑snippets/serializers.py:

class SnippetSerializer(serializers.HyperlinkedModelSerializer):
    owner = serializers.ReadOnlyField(source='owner.username')
    highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html')

    class Meta:
        model = Snippet
        fields = ['url', 'id', 'highlight', 'owner',
                  'title', 'code', 'linenos', 'language', 'style']


class UserSerializer(serializers.HyperlinkedModelSerializer):
    snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True)

    class Meta:
        model = User
        fields = ['url', 'id', 'username', 'snippets']
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

这里新增了一个highlight字段,这个字段和url字段类型相同,区别就是它指向snippet-highlight而非snippet-detail。

由于我们有.json格式的后缀,所以我们也要指明highlight字段使用.html来返回相应的格式。

# 为 URL 命名

如果我们创建了一个基于超链接的 API,我们需要确保每个 URL 都被命名了。让我们看看那些需要被命名的 URL:

  • 根 URL 包含'user-list'和'snippet-list'
  • snippet serializer 包含指向'snippet-highlight'的字段
  • user serializer 包含指向'snippet-detail'的字段
  • snippet serializers 和 user serializers 包含'url'字段,这个字段默认指向'{model_name}-detail',这里分别是'snippet-detail'和'user-detail'

最终,我们的snippets/urls.py如下:

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

# API endpoints
urlpatterns = format_suffix_patterns([
    path('', views.api_root),
    path('snippets/',
        views.SnippetList.as_view(),
        name='snippet-list'),
    path('snippets/<int:pk>/',
        views.SnippetDetail.as_view(),
        name='snippet-detail'),
    path('snippets/<int:pk>/highlight/',
        views.SnippetHighlight.as_view(),
        name='snippet-highlight'),
    path('users/',
        views.UserList.as_view(),
        name='user-list'),
    path('users/<int:pk>/',
        views.UserDetail.as_view(),
        name='user-detail')
])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 分页

列表视图可能为用户返回很多代码片段,所以我们需要对结果进行分页,并且可以遍历每个单独的页面。

我们可以使用分页来修改默认的列表样式,修改tutorial/settings.py添加:

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10
}
1
2
3
4

注意,所有关于 REST 框架的设定都在一个叫做'REST_FRAMEWORK'的字典中,这帮助我们将设定信息和其他的库分离开来。

如果需要的话我们也可以自定义分页样式,但这里我们先使用默认选项。

# 测试

打开浏览器,就会发现你可以使用超链接来简单的浏览 API 了。你也会在 snippet 中看到'highlight'链接,这将返回高亮的 HTML 格式代码。

在本教程的第 6 部分中,我们将看看如何使用视图和路由器来减少构建 API 所需的代码量。

编辑 (opens new window)
#DRF
上次更新: 2024-07-23, 01:00:43
教程 4:认证和权限
教程 6:ViewSets 和 Routers

← 教程 4:认证和权限 教程 6:ViewSets 和 Routers→

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