在DRF中使用HyperlinkedModelSerializer有什么好处?

Tim*_* S. 44 python django django-rest-framework

在参考这个链接时,我已经看到很多在Django Rest Framework中使用HyperlinkedModelSerializer的例子.它说:

HyperlinkedModelSerializer类与ModelSerializer类类似,不同之处在于它使用超链接来表示关系,而不是主键.

我的问题是,使用它们与常规模型序列化器的用例/好处是什么?

Ser*_*jik 37

我们需要在Web API设计中实现实体之间的关系.有几种方法可以做到这一点(如DRF文档所述):

  • 使用主键.
  • 在实体之间使用超链接.
  • 在相关实体上使用唯一标识段塞字段.
  • 使用相关实体的默认字符串表示形式.
  • 将相关实体嵌套在父表示中.
  • 一些其他自定义表示

HyperlinkedModelSerializer与ModelSerializer有以下不同之处:

  • 默认情况下,它不包含id字段.
  • 它包含一个url字段,使用HyperlinkedIdentityField.
  • 关系使用HyperlinkedRelatedField而不是PrimaryKeyRelatedField.

一个简单的例子:

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = ('url', 'username', 'email', 'groups')


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Group
        fields = ('url', 'name')
Run Code Online (Sandbox Code Playgroud)

bash> http -a admin:yourpassword http://127.0.0.1:8000/users/

 "results": [
        {
            "email": "admin@min.com",
            "groups": [
                "http://127.0.0.1:8000/groups/1/",
                "http://127.0.0.1:8000/groups/2/"
            ],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        }
    ]
Run Code Online (Sandbox Code Playgroud)

但如果你改变了

class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ('url', 'username', 'email', 'groups')
Run Code Online (Sandbox Code Playgroud)

结果将是:

   "results": [
        {
            "email": "admin@min.com",
            "groups": [
                1,
                2
            ],
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin"
        }
    ]
Run Code Online (Sandbox Code Playgroud)


Iva*_*van 30

唯一的区别在于,如您所引用的那样,主键和外键由指向这些资源的URL表示,而不仅仅是实际的键值.

好处是,当您想要检索相关对象时,您不必在前端构建资源URL.

完全另一件事是嵌套表示,它允许您在串行器输出中内联相关对象.这可以与两者结合使用,ModelSerializer并且HyperlinkedModelSerializer当您认为API使用者更方便地立即拥有相关项目而不是另外请求检索它们时.

嵌套表示可以通过Meta.depth选项或使用相关模型的序列化器而不是a来实现RelatedField.

正如@xleon在评论中所说的那样,使用URL作为密钥使其他开发人员更容易理解您的API.

  • 很好的答案,我只想添加一件事:在您的资源中使用超链接将使任何使用您的Web API的开发人员更容易.如果他们可以看到整个资源URI,他们就不需要任何文档或其他方法来找到它 (7认同)

Col*_*cks 11

应该注意的 HyperlinkedModelSerializers 的一项成本是,如果您的 API 支持通过 URL 中的查询参数进行过滤或排序,那么您的前端使用者使用超链接 url 字段来构建查询参数会有点困难,因为他们必须解析出从 URL 获取 pk,而不是直接获取 pk。

例如,假设/api/objects/12/消费者的路由上的对象需要解析字段url以提取 ,12以便通过另一个端点上的该对象构建查询过滤:/api/otherobjects/?object=12。这不是一个大问题,但如果您打算进行大量过滤,那就太糟糕了。

  • 解决这个问题的简单方法是在序列化器中添加“id”字段:“id =serializers.ReadOnlyField()” (20认同)