Django 行为良好的RESTful客户端交互

Django 行为良好的RESTful客户端交互,django,rest,Django,Rest,关于实现严格遵守REST体系结构原则的数据访问客户机,我有一个似乎相当简单的问题。首先,假设我有一个性能良好的RESTAPI,我想使用Django应用程序使用它。我将首先了解哪些服务可用(编辑以供后续使用): GET example.com/services/ HTTP/1.1 HTTP/1.1 200 OK <?xml version="1.0" encoding="UTF-8"?> <services> <service> <name&

关于实现严格遵守REST体系结构原则的数据访问客户机,我有一个似乎相当简单的问题。首先,假设我有一个性能良好的RESTAPI,我想使用Django应用程序使用它。我将首先了解哪些服务可用(编辑以供后续使用)

GET example.com/services/ HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<services>
  <service>
    <name>Widgets</name>
    <link>http://example.com/services/widgets/</link>
    <item_link>http://example.com/services/widgets/{widget_id}/</item_link>
  </service>
  <service>
    <name>Factories</name>
    <link>http://example.com/services/factories/</link>
    <item_link>http://example.com/services/factories/{factory_id}/</item_link>
  </service>
  ...
</services>
GET example.com/services/widgets/ HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<widgets>
  <item_link>http://example.com/services/widgets/{widget_id}/</item_link>
  <widget>
    <id>1</id>
    <name>Whizbang Foobar</name>
    <link>http://example.com/services/widgets/1</link>
  </widget>
  ...
</widgets>
我将从中执行另一个请求(为后续操作而编辑)

GET example.com/services/ HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<services>
  <service>
    <name>Widgets</name>
    <link>http://example.com/services/widgets/</link>
    <item_link>http://example.com/services/widgets/{widget_id}/</item_link>
  </service>
  <service>
    <name>Factories</name>
    <link>http://example.com/services/factories/</link>
    <item_link>http://example.com/services/factories/{factory_id}/</item_link>
  </service>
  ...
</services>
GET example.com/services/widgets/ HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<widgets>
  <item_link>http://example.com/services/widgets/{widget_id}/</item_link>
  <widget>
    <id>1</id>
    <name>Whizbang Foobar</name>
    <link>http://example.com/services/widgets/1</link>
  </widget>
  ...
</widgets>
随后的请求:

GET example.com/services/widgets/1 HTTP/1.1

HTTP/1.1 200 OK
<?xml version="1.0" encoding="UTF-8"?>
<widget>
  <id>1</id>
  <name>Whizbang Foobar</name>
  <tags>foo bar baz ham eggs</tags>
  <index_link>http://example.com/services/widgets/</index_link>
</widget>
GET example.com/services/widgets/1 HTTP/1.1
HTTP/1.1200ok
1.
惠茨邦福巴酒店
福巴火腿蛋
http://example.com/services/widgets/

如果我正确理解您的问题,您想探索未知服务,对吗

如果是这样,那么您可以继续向“小部件”资源发出
OPTIONS
请求,查看它支持哪些HTTP方法(这些方法应列在响应的
Allow
标题中)。
然后,您可以对
元素中的所有URI执行相同的操作。如果以这种方式找到的资源表明它支持
GET
,则获取它并重复…
这样,您应该能够浏览所有嵌套资源

当然,这种探索只会让您走到这一步,因为要真正与服务交互,您需要了解它的媒体类型(或表示),以及您发现的不同
操作实际上意味着什么。这一步无法自动化,您必须阅读服务文档并相应地构建您的客户机。我建议阅读文章“”,我认为这篇文章很好地解释了这种交互作用。

文档是RESTful API的一个很好的例子,重点是媒体类型

我主要担心的是,如果不严格遵守REST体系结构指南,这是一件微不足道的事情,但我觉得这样做完全是徒劳的。我知道设计适当的RESTAPI和客户端并不“容易”,但似乎我迫切需要一个类似的示例来完成实际的实现

我能找到的最好的例子就是。大多数文档描述了系统使用的各种媒体类型,这似乎是实现这类功能的关键

我发现在开发API的同时编写客户机很有帮助。通过这种方式,您可以发现什么可能会使您的API立即成为代码的难点,并解决问题

这并不容易。如果遵循HATEOAS约束的逻辑结论,则定义的每种媒体类型都将由一系列客户机中的一个来处理。如果您可以使所有资源遵循类似的行为模式,那么编写客户机的工作将变得更容易

例如,您可以定义一个只列出相关资源的媒体类型“索引”。索引定义用于分页、获取列表中的项目、按名称查找项目等的链接

然后,您可以定义一个名为“Item”的基本媒体类型。项目有一个用于显示其父索引、更新/删除自身等的链接。然后,您的资源小部件可以由两种不同的媒体类型表示—一种是索引,另一种是基于项目的

您可以首先实现一个处理索引媒体类型的类。然后您可以编写一个基类来处理所有常见的项媒体类型行为。最后,您可以编写一个小部件客户端来处理所有小部件特定的行为,并扩展项目客户端。这些客户机可以用自己编写的语言以惯用的方式公开其功能(更多链接和数据字段的可用性)

然后,处理来自服务器的响应就需要将响应的mime类型与您编写的某个客户端进行匹配


换言之,即使您的整个服务的客户将由许多范围有限的客户组成,它们都基于常见的行为,因此可以以干燥的方式实现。

根据我的经验,如果表示形式及其包含的链接直接转换到客户端UI,REST模型会更有意义。在这个场景中,是用户指导探索REST界面

我经常看到人们试图使用REST接口作为一种基于HTTP的数据访问层。通过这种心智模型,超链接数据只提供了结构数据关系。在不违反RESTful约束的情况下,很难在该接口之上构建应用程序行为

我喜欢将RESTful界面看作是将UI内容交付给将使用某种任意技术呈现该内容的应用程序。不幸的是,REST经常被比作web服务,在我看来,web服务适合不同的体系结构层。Web服务提供将由客户端应用程序处理的数据。RESTful接口应提供将呈现给用户的内容

当然,您可以使用REST接口将数据传送到远程应用程序,但可以将其视为简化的屏幕抓取


在为REST接口编写客户机时,我发现很有用的一点是,我正在编写一个自定义web浏览器,它只理解RESTful接口交付的媒体类型,并且硬编码为从特定URL开始,并且没有地址栏

谢谢你的明确答复。云API及其对媒体类型的关注大大增强了我的理解。作为后续行动,在资源的“索引”媒体类型中使用URI模板是否可以作为发现资源“项目”的适当方式(请参阅问题编辑和后续行动)?可能,但我不确定是否有必要。如何定义索引媒体类型以包括(分页的)项目链接列表?分页链接,就像HTML视图一样,可以用来引导客户端浏览项目列表。@m0