Django 将REST和RPC混合在一起是一种糟糕的做法吗?

Django 将REST和RPC混合在一起是一种糟糕的做法吗?,django,rest,rpc,django-rest-framework,Django,Rest,Rpc,Django Rest Framework,我对RESTweb服务相当陌生,并且非常习惯RPC。通过阅读几篇类似于一篇的文章,我知道了REST的优点 我正在使用django rest框架在django中开发服务器 尽管有以下问题: 我有这个模型: class Poll(models.Model): questionString = models.CharField(max_length=500, blank=True) timeToAnswer = models.IntegerField(default=30) s

我对RESTweb服务相当陌生,并且非常习惯RPC。通过阅读几篇类似于一篇的文章,我知道了REST的优点

我正在使用django rest框架在django中开发服务器

尽管有以下问题:

我有这个模型:

class Poll(models.Model):
    questionString = models.CharField(max_length=500, blank=True)
    timeToAnswer = models.IntegerField(default=30)
    startDate = models.DateTimeField(null=True, db_column='startDate', blank=True)
    token = models.CharField(max_length=20, blank=True, unique=True)

class PollAggregator(models.Model):

    name = models.CharField(max_length=135)
    description = models.CharField(max_length=500, blank=True)
    votersToken = models.CharField(max_length=20, null=True, blank=True)

class PollPollAggregatorRel(models.Model):
    pollAggregator = models.ForeignKey(PollAggregator, null=True, db_column='pollAggregatorId', blank=True)
    poll = models.ForeignKey(Poll, null=True, db_column='pollId', blank=True)
因此,我可以进行一次投票,也可以在投票聚合器(即房间)中聚合一组投票

所以我创建了其余调用:pollList、pollDetail、pollAggregatorList、pollAggregatorDetail。但是我有问题要为Pollagregatorrel设计。 当然,我可以使用pollagregatorrellist和pollagregatorreldetail,进行正常的发布、获取、更新和删除。因此,如果我想在REST样式的轮询和轮询聚合器之间建立新关系,我会:

  • 检查PollaGragator(列表)是否存在,其轮询id为get并按pollId进行筛选
  • 如果是这样,我将更新此项以获得新的轮询聚合器id
  • 如果没有,我将创建一个新的pollagregator,其中包含一个post
我的第一个问题是有没有更简单更简单的方法

如果我使用类似RPC的web服务,我会执行以下操作:

  • 将轮询与pollAggregator关联,并为PollAggregatorRel使用get_或_create。所以我更新或创建了一个新的PollAggregatorRel对象
因此,使用类似RPC的方法,客户端只使用一个调用,而REST需要调用两次。在这种情况下,对服务器端和客户端使用RPC似乎要简单得多


第二个问题是:在同一个API中同时使用REST和RPC是一种不好的做法吗?

Q1:我认为提供REST风格的POST操作是合理的,它可以返回现有的聚合器,也可以根据需要创建新的聚合器。从逻辑上讲,这似乎与您的“RPC”服务没有什么不同

我认为您的部分困难可能是您设计的REST“调用”(提示:它们不是“调用”,而是“资源”)过于接近底层模型。这是我过去犯的一个错误

休息!=积垢

REST的一个关键好处是,它允许将接口与模型分离,因此服务器可以在不影响客户端的情况下更改其实现。另一个关键好处是,它最大限度地减少了客户执行某些操作之前需要知道的信息量。例如,REST客户端应该能够通过与服务的“前端资源”(类似于“前端页面”)交互来发现它需要使用的所有资源URI

因此,我将考虑以下的一种方法来描述上面所描述的资源:

  • 服务主页,其表示形式包含指向其他资源的链接(或链接模板)(或通过HTTP链接头返回链接)

  • “轮询集合”资源,用于创建和访问单个轮询(例如,获取所有轮询的返回列表,POST创建新轮询)

  • 单个轮询,通过与“轮询集合”的交互发现其URI。获取、放置、删除—按您的预期操作。我不确定你是否需要这些邮件

  • 将轮询与聚合关联的“聚合管理器”资源(轮询可以属于多个聚合吗?——您的描述表明不是)。包含轮询URI的对此资源的帖子可以定位或创建聚合(或聚合?)或创建新的聚合。GET可能返回现有聚合的列表

  • 通过与聚合管理器资源的交互发现其URI的单个聚合资源

  • 在您的描述中,PollAggregatorRel是(当前)实现的一部分,而不是通过RESTAPI公开的内容。这使您能够灵活地更改内部实现,而不会影响客户端使用API的方式。这就是休息的重点

    我不确定你是否会认为这“更简单更简单”,但这不是休息的重点。Roy Fielding将REST描述为“几十年规模的软件工程”,重点是创建一个接口,允许客户端和服务器实现相对独立的演化,这对于以web规模运行的应用程序至关重要。这是要付出代价的,客户机必须与服务器交互,以发现进行交互所需的信息

    < P> Q2:我认为把REST和RPC混合到同一个API中是不明智的。(将REST公开给外部客户机并在内部使用RPC,或者提供单独的API,这可能非常有意义。)


    我这样做的理由是,如果您主要使用REST API,那么添加RPC元素可能会在客户机和服务器之间产生紧密耦合,而不是首先否定使用REST的意义。

    Great post!谢谢