在REST-ful api中序列化外键字段的最佳做法是什么

时间:2022-02-16 10:18:38

I want to write a Django app with a REST-ful api. Django REST framework offers three built-in model serializers: ModelSerializer which serializes to something like this

我想用REST-ful api编写一个Django应用程序。 Django REST框架提供了三个内置的模型序列化器:ModelSerializer,它序列化为类似的东西

{
    'normal_field': 'value',
    'foreign_key_field': 42
}

and HyperlinkedModelSerializer which serializes to something like this

和HyperlinkedModelSerializer序列化为这样的东西

{
    'normal_field': 'value',
    'foreign_key_field': 'http://domain/api/myothermodel/11'
}

My question is whether there is another good way to serialize the data so that the client directly knows which fields have to be resolved and which fields not.

我的问题是,是否有另一种好的方法来序列化数据,以便客户端直接知道哪些字段必须被解析,哪些字段不被解析。

Example: A client which receives this

示例:接收此内容的客户端

{ 
    'foo': 'http://domain/api/myothermodel/11',
    'bar': 'http://otherdomain/api/myothermodel/12'
}

does not know whether foo or bar should be a resolveable foreign key field and not a plain url. Something like:

不知道foo或bar是否应该是可解析的外键字段而不是普通的url。就像是:

{ 
    'foo': 'http://domain/api/myothermodel/11', # Here the client might know that this is only a plain url.
    'bar': {
            '_foreignkey': true,  # Tells the client that this field should behave as a foreign key which has to be resolved first
            'url': 'http://otherdomain/api/myothermodel/12'
        }
}

Is there any standard or best practice? Or is best practice that the client does not know this from the JSON but from other code it has or gets from the server?

有没有标准或最佳做法?或者最好的做法是客户端不是从JSON知道这个,而是从服务器上获得或从服务器获取的其他代码?

Update: Optional you can add which way is best practice for some wellknown client side libs like AngularJS.

更新:可选您可以为AngularJS等一些知名的客户端库添加哪种方式是最佳实践。

1 个解决方案

#1


5  

It appears you are after a self-describing and explorable web API service, which is actually a core feature of the original REST concept referred to as Hypermedia as the Engine of Application State (HATEOAS). Essentially, a HATEOAS-compliant web service does not rely upon any prior knowledge of the system's resources other than the initial URL entry point.

您似乎正在使用自我描述和可探索的Web API服务,这实际上是原始REST概念的核心功能,称为超媒体作为应用程序状态引擎(HATEOAS)。从本质上讲,符合HATEOAS标准的Web服务不依赖于除初始URL入口点之外的系统资源的任何先验知识。

This is in contrast to a Service Oriented Architecture (SOA) where individual services are basically unassociated and require prior knowledge of their existence to string together several service calls to accomplish some task with multiple, possibly related resources.

这与面向服务的体系结构(SOA)形成对比,在面向服务的体系结构中,各个服务基本上没有关联,并且需要事先了解它们的存在,以将多个服务调用串联起来以使用多个可能相关的资源完成某些任务。

Most references to a REST API are actually not fully RESTful, and should more accurately be described as web APIs, as they are more in-line with the SOA design: a set of URLs to both specific instances and collections of instances of a particular type. This would also include the use of different HTTP verbs (GET, PATCH, POST, PUT) for various actions to perform on those resources. The Django REST Framework (DRF) actually has a page on this topic with links to some great resources on the true RESTful design, including the dissertation by Roy Fielding:

大多数对REST API的引用实际上并不完全是REST,并且应该更准确地描述为Web API,因为它们更符合SOA设计:一组特定实例的URL和特定类型实例的集合。这还包括使用不同的HTTP谓词(GET,PATCH,POST,PUT)来执行对这些资源执行的各种操作。 Django REST框架(DRF)实际上有一个关于这个主题的页面,其中包含有关真正RESTful设计的一些重要资源的链接,包括Roy Fielding的论文:

http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas

I would speculate that the current use of the term "REST API" relates to the revelation of many developers that implementing a truly RESTful service is far from trivial and in many cases would be over-engineered for the particular use case. Perhaps this is a good example of "perfection as the enemy of the good." For the case of using AngularJS as a client-side framework for interacting with a Django backend via DRF, this is especially true. There is nothing in the AngularJS framework that parses a truly RESTful design to automagically provide the various application states possible for a given resource. Plus, the same developer(s) will usually be responsible for both the JavaScript and Python code, so the lack of a self-describing API is not a major barrier to development.

我推测当前使用术语“REST API”涉及许多开发人员的启示,即实现真正的RESTful服务远非微不足道,并且在许多情况下会针对特定用例进行过度设计。也许这是“作为善的敌人的完美”的一个很好的例子。对于使用AngularJS作为客户端框架通过DRF与Django后端进行交互的情况,尤其如此。 AngularJS框架中没有任何内容可以解析真正的RESTful设计,以自动为给定资源提供各种应用程序状态。此外,相同的开发人员通常负责JavaScript和Python代码,因此缺乏自描述API不是开发的主要障碍。

Regarding the implementation of a truly RESTful API in JSON, there are a couple projects attempting to facilitate this, namely the Hypertext Application Language (HAL) and JSON Linked Data (JSON-LD). However, I am not aware that DRF natively supports either of these, so you would likely have to architect your serializers to conform to one of them, or roll your own Django REST implementation.

关于在JSON中实现真正的RESTful API,有几个项目试图促进这一点,即超文本应用程序语言(HAL)和JSON关联数据(JSON-LD)。但是,我不知道DRF本身支持这些中的任何一个,因此您可能必须构建序列化程序以符合其中一个,或者滚动您自己的Django REST实现。

Finally, whatever design you choose, fully documenting the API is usually a good idea. This is true regardless of whether the API is web-based or in some native programming language. Part of the allure for the separation of concerns that a web API provides is that 3rd parties can consume resources to build applications or pipelines that you haven't considered, not to mention the advantages in maintainability for future changes to the code base for your project. There are a couple interesting projects mentioned on the DRF site to assist in documenting an API. Swagger is a particularly awesome one, developed by the same developer that provided the older Django REST Framework Docs package.

最后,无论您选择何种设计,完全记录API通常都是一个好主意。无论API是基于Web还是使用某种本机编程语言,都是如此。 Web API提供的关注点分离的部分吸引力在于第三方可以消耗资源来构建您未考虑过的应用程序或管道,更不用说为将来更改项目代码库的可维护性的优势。 DRF网站上提到了一些有趣的项目,以帮助记录API。 Swagger是一个特别棒的,由同一个提供较旧的Django REST Framework Docs包的开发人员开发。

#1


5  

It appears you are after a self-describing and explorable web API service, which is actually a core feature of the original REST concept referred to as Hypermedia as the Engine of Application State (HATEOAS). Essentially, a HATEOAS-compliant web service does not rely upon any prior knowledge of the system's resources other than the initial URL entry point.

您似乎正在使用自我描述和可探索的Web API服务,这实际上是原始REST概念的核心功能,称为超媒体作为应用程序状态引擎(HATEOAS)。从本质上讲,符合HATEOAS标准的Web服务不依赖于除初始URL入口点之外的系统资源的任何先验知识。

This is in contrast to a Service Oriented Architecture (SOA) where individual services are basically unassociated and require prior knowledge of their existence to string together several service calls to accomplish some task with multiple, possibly related resources.

这与面向服务的体系结构(SOA)形成对比,在面向服务的体系结构中,各个服务基本上没有关联,并且需要事先了解它们的存在,以将多个服务调用串联起来以使用多个可能相关的资源完成某些任务。

Most references to a REST API are actually not fully RESTful, and should more accurately be described as web APIs, as they are more in-line with the SOA design: a set of URLs to both specific instances and collections of instances of a particular type. This would also include the use of different HTTP verbs (GET, PATCH, POST, PUT) for various actions to perform on those resources. The Django REST Framework (DRF) actually has a page on this topic with links to some great resources on the true RESTful design, including the dissertation by Roy Fielding:

大多数对REST API的引用实际上并不完全是REST,并且应该更准确地描述为Web API,因为它们更符合SOA设计:一组特定实例的URL和特定类型实例的集合。这还包括使用不同的HTTP谓词(GET,PATCH,POST,PUT)来执行对这些资源执行的各种操作。 Django REST框架(DRF)实际上有一个关于这个主题的页面,其中包含有关真正RESTful设计的一些重要资源的链接,包括Roy Fielding的论文:

http://www.django-rest-framework.org/topics/rest-hypermedia-hateoas

I would speculate that the current use of the term "REST API" relates to the revelation of many developers that implementing a truly RESTful service is far from trivial and in many cases would be over-engineered for the particular use case. Perhaps this is a good example of "perfection as the enemy of the good." For the case of using AngularJS as a client-side framework for interacting with a Django backend via DRF, this is especially true. There is nothing in the AngularJS framework that parses a truly RESTful design to automagically provide the various application states possible for a given resource. Plus, the same developer(s) will usually be responsible for both the JavaScript and Python code, so the lack of a self-describing API is not a major barrier to development.

我推测当前使用术语“REST API”涉及许多开发人员的启示,即实现真正的RESTful服务远非微不足道,并且在许多情况下会针对特定用例进行过度设计。也许这是“作为善的敌人的完美”的一个很好的例子。对于使用AngularJS作为客户端框架通过DRF与Django后端进行交互的情况,尤其如此。 AngularJS框架中没有任何内容可以解析真正的RESTful设计,以自动为给定资源提供各种应用程序状态。此外,相同的开发人员通常负责JavaScript和Python代码,因此缺乏自描述API不是开发的主要障碍。

Regarding the implementation of a truly RESTful API in JSON, there are a couple projects attempting to facilitate this, namely the Hypertext Application Language (HAL) and JSON Linked Data (JSON-LD). However, I am not aware that DRF natively supports either of these, so you would likely have to architect your serializers to conform to one of them, or roll your own Django REST implementation.

关于在JSON中实现真正的RESTful API,有几个项目试图促进这一点,即超文本应用程序语言(HAL)和JSON关联数据(JSON-LD)。但是,我不知道DRF本身支持这些中的任何一个,因此您可能必须构建序列化程序以符合其中一个,或者滚动您自己的Django REST实现。

Finally, whatever design you choose, fully documenting the API is usually a good idea. This is true regardless of whether the API is web-based or in some native programming language. Part of the allure for the separation of concerns that a web API provides is that 3rd parties can consume resources to build applications or pipelines that you haven't considered, not to mention the advantages in maintainability for future changes to the code base for your project. There are a couple interesting projects mentioned on the DRF site to assist in documenting an API. Swagger is a particularly awesome one, developed by the same developer that provided the older Django REST Framework Docs package.

最后,无论您选择何种设计,完全记录API通常都是一个好主意。无论API是基于Web还是使用某种本机编程语言,都是如此。 Web API提供的关注点分离的部分吸引力在于第三方可以消耗资源来构建您未考虑过的应用程序或管道,更不用说为将来更改项目代码库的可维护性的优势。 DRF网站上提到了一些有趣的项目,以帮助记录API。 Swagger是一个特别棒的,由同一个提供较旧的Django REST Framework Docs包的开发人员开发。