路径参数的REST API URL模式

时间:2016-02-21 20:15:52

标签: rest django-rest-framework url-parameters

我正在构建一个Backbone应用程序,它可以显示某些技术手册中图表的交互式传真。每本手册都有许多图表类型(比如A-Z),分布在它的页面上。每个图表可能在页面中出现多次,有时单个页面可能包含给定图表类型的多个实例。

我有一个Django后端服务于我的前端消耗的REST API。我一直在努力的是设计请求的URL。我尝试了几种模式,但都没有让我满意。我的Django模型看起来像这样:

class Diagram(models.Model):
    type = models.CharField(max_length=1)
    page = models.IntegerField(default=1)
    order = models.IntegerField(default=1)
    data = JSONField(default='{}')

order字段与页面上给定图表类型有多个实例的情况有关。这个模型的表是只读的,所以我只是做简单的GET。用户一次只能查看一个图表实例。按类型,页面和(如果相关)顺序选择图表。我最初的网址设计是这样的:

example.org/api/diagrams/A/pages/1/order/2/

虽然有多个图表,但diagrams参数表示集合 - 但图表不包含“页面”。与pages param相同。显然order只能是单数。所以也许:

example.org/api/diagrams/type=A/page=1/order=2/

或者只是选择查询参数:

example.org/api/diagrams/?type=A&page=1&order=2

我个人更喜欢路径参数,但主要的复杂性是order param在大多数情况下实际上是冗余的 - 在页面上只有少量重复图表的情况(目前我在后端和请求中都默认order为'1'。所以可能是路径和查询参数的组合:

example.org/api/diagrams/A/page/1/?order=2

这是一个好模式吗?我还可以考虑其他替代方案吗?

编辑:经过一些额外的阅读(特别是URI Standard)我认为答案是路径参数设计适合分层结构。这似乎很直观。但我没有,所以正确的候选者是纯查询参数设计。正确?

1 个答案:

答案 0 :(得分:4)

我可以建议一种不同的方法吗?我知道,这可能不是您正在寻找的答案,但不是试图从您的代码中发布确切的对象模型,而是考虑客户需要查看的“类型”资源以及与之相关的内容。

例如,如果客户端需要“浏览”图表,则可以有2个media-types,一个用于列出所有图表,以及单个图表本身。 URI可以是:

/api/diagrams/          <-- list of all diagrams with titles
/api/diagrams/1         <-- a single diagram
/api/diagrams/2
...

如果客户端需要每页浏览每个手册,那么您也可以提供附加media-types表示手册(页面列表)的页面,以及带有指向其上图表的链接的页面。例如:

/api/manuals         <-- list of all manuals
/api/manuals/1       <-- list of pages, maybe a list of all diagrams in manual
/api/manuals/1/page2 <-- list of diagrams on page2

关于每个订单和图表类型的浏览情况也是如此。

如果您只需要“搜索”API,而不是“浏览”API,那么正确的解决方案是创建一个“表单”,您可以在其中提交信息(订单,类型,页面等) 。所以这将是2 media-types,一个用于搜索描述,可能一个用于图表。

关键是,如果您尝试创建REST API,则不应修复URI。服务器应该向客户端提供URI(例如,起始URI,搜索页面除外)。

这有几个优点,一个是您可以控制服务器上的URI。如果你不想,你不必是RESTful,但即便如此,如果你控制客户端,URI本身并不重要。客观的衡量标准都没有弄错。

很抱歉,如果这没有帮助。:)