部分更新(又名PATCH)使用基于资源的服务?

时间:2013-10-08 21:01:28

标签: angularjs tastypie

我们正在构建一个使用Django / TastyPie作为后端REST服务提供程序的Web应用程序,并构建一个基于AngularJS的前端,使用大量基于$ resource的服务来处理服务器上的CRUD对象。到目前为止,一切都很好!

但是,我们希望在我们只想更新对象上的一个或两个已更改字段时减少我们要传输的数据量。

TastyPie使用HTTP PATCH方法支持此功能。我们在对象上定义了一个.diff()方法,因此我们可以确定在进行更新时要发送哪些字段。我找不到任何关于如何在$ resource返回的实例对象上定义/实现该方法以执行我们想要的文档。

我们想要做的是向对象实例添加另一个方法,(as described in the Angular.js documentation here),如 myobject。$ partialupdate(),它将:

  1. 调用我们的.diff()函数来确定要发送的字段,然后
  2. 使用HTTP PATCH请求仅将这些字段发送到服务器。
  3. 到目前为止,我找不到任何描述如何执行此操作的文档(或其他SO帖子),但我们非常感谢任何人可能提出的任何建议。

    谢谢。

3 个答案:

答案 0 :(得分:14)

我建议使用

update: {
    method: 'PATCH',
    transformRequest: dropUnchangedFields
}

,其中

var dropUnchangedFields = function(data, headerGetter) {

    /* compute from data using your .diff method by  */
    var unchangedFields = [ 'name', 'street' ];

    /* delete unchanged fields from data using a for loop */ 
    delete data['name'] ;
    delete data['street'];

    return data;

}

PS:内存不确定data是否是对其副本的资源的引用,因此您可能需要在删除字段之前创建data的副本

此外,您可能需要return data而不是return JSON.stringify(data)


Source(搜索" transformRequest"在documentation page上)

答案 1 :(得分:4)

我们使用ngResource实现了$patch,但它有点涉及(我们在服务器端使用Django Rest Framework)。对于您的diff组件,我将留给您自己的实施。我们使用原始缓存来跟踪资源的变化,因此我可以轮询给定的对象并查看更改的内容(如果有的话)。

我利用下划线的_.pick()方法提取已知字段以保存现有实例,创建副本(以及已知主键)并使用$patch保存。

我们还使用一些实用程序类来扩展内置资源。

app.factory 'PartUpdateMixin', ['$q', '_', ($q, _) ->

    PartUpdateMixin = (klass) ->
        partial_update: (keys...) ->
            deferred = $q.defer()
            params = _.pick(@, 'id', keys...)
            o = new klass(params)
            o.$patch(deferred.resolve, deferred.reject)
            return deferred.promise
]

这是增强资源的实用程序类。

app.factory 'extend', ->
    extend = (obj, mixins...) ->
        for mixin in mixins
            obj[name] = method for name, method of mixin
        obj

app.factory 'include', ['extend', (extend) ->
    include = (klass, mixins...) ->
        extend klass.prototype, mixins...

    return include
]

最后,我们可以增强我们的资源

include TheResource, PartUpdateMixin(TheResource)
resourceInstance = TheResource.get(id: 1234)
# Later...
updatedFields = getChangedFields(resourceInstance)
resourceInstance.partial_update(updatedFields...)

答案 2 :(得分:2)

我建议使用Restangular而不是ngResource。角度团队不断改进每个版本的ngResource,但Restangular仍然做得更多,包括允许像ngResource那样的PATCH等动作。这是一个很好的问题,比较两个What is the advantage of using Restangular over ngResource?