10

We're building a web application using Django/TastyPie as the back-end REST service provider, and building an AngularJS based front end, using lots of $resource based services to CRUD objects on the server. Everything is working great so far!

But, we would like to reduce the amount of data that we're shipping around when we want to update only one or two changed fields on an object.

TastyPie supports this using the HTTP PATCH method. We have defined a .diff() method on our objects, so we can determine which fields we want to send when we do an update. I just can't find any documentation on how to define/implement the method on the instance object returned by $resource to do what we want.

What we want to do is add another method to the object instances, (as described in the Angular.js documentation here) like myobject.$partialupdate() which would:

  1. Call our .diff() function to determine which fields to send, and then
  2. Use an HTTP PATCH request to send only those fields to the server.

So far, I can't find any documentation (or other SO posts) describing how to do this, but would really appreciate any suggestions that anyone might have.

thank you.

4

3 回答 3

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).


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

于 2014-04-28T15:04:57.350 回答
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
]

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

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...)
于 2013-10-09T06:37:25.370 回答
2

我建议在 ngResource 上使用Restangular。Angular 团队不断改进每个版本的 ngResource,但 Restangular 仍然做得更多,包括允许 ngResource 不允许的 PATCH 等操作。Here'a a great SO question比较两者使用Restangular优于ngResource有什么优势?

于 2013-10-08T22:11:19.017 回答