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

Eri*_*rik 10 tastypie angularjs

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

但是,当我们想要仅更新对象上的一个或两个已更改字段时,我们希望减少我们传送的数据量.

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

我们想要做的是向对象实例添加另一个方法(如此处的Angular.js文档中所述),如myobject.$ partialupdate(),它将:

  1. 调用我们的.diff()函数来确定要发送的字段,然后
  2. 使用HTTP PATCH请求仅将这些字段发送到服务器.

到目前为止,我找不到任何描述如何执行此操作的文档(或其他SO帖子),但非常感谢任何人可能提出的任何建议.

谢谢.

iPi*_*rat 14

我建议使用

update: {
    method: 'PATCH',
    transformRequest: dropUnchangedFields
}
Run Code Online (Sandbox Code Playgroud)

哪里

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;

}
Run Code Online (Sandbox Code Playgroud)

PS:不确定是否从内存中,是否data是对你的资源副本的引用,所以你可能需要data在删除字段之前创建一个副本

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


来源(在文档页面上搜索"transformRequest" )


Kev*_*one 4

我们$patch使用 ngResource 实现,但有点复杂(我们在服务器端使用 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
]
Run Code Online (Sandbox Code Playgroud)

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

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
]
Run Code Online (Sandbox Code Playgroud)

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

include TheResource, PartUpdateMixin(TheResource)
resourceInstance = TheResource.get(id: 1234)
# Later...
updatedFields = getChangedFields(resourceInstance)
resourceInstance.partial_update(updatedFields...)
Run Code Online (Sandbox Code Playgroud)