2013-04-29 53 views
2

查了一些其他的问题,我想我的tastypie资源应该是这个样子:使用Backbone将文件上传到tastypie?

class MultipartResource(object): 
    def deserialize(self, request, data, format=None): 
     if not format: 
      format = request.META.get('CONTENT_TYPE', 'application/json') 

     if format == 'application/x-www-form-urlencoded': 
      return request.POST 

     if format.startswith('multipart'): 
      data = request.POST.copy() 
      data.update(request.FILES) 

      return data 

     return super(MultipartResource, self).deserialize(request, data, format) 


class ImageResource(MultipartResource, ModelResource): 

    image = fields.FileField(attribute="image") 

请告诉我,如果这是错误的。

假设上面是正确的,我没有得到什么传递给资源。这里是一个文件输入:

<input id="file" type="file" /> 

如果我有一个骨干模型IMG什么我设置图像?

img.set("image", $("#file").val()); // tastypie doesn't store file, it stores a string 
img.set("image", $("#file").files[0]); // get "{"error_message": "'dict' object has no attribute '_committed'" ... 

我怎么把我的脊梁“图像”属性,这样我可以上传文件通过Ajax来tastypie?

回答

1

您可以覆盖sync方法以FormData api序列化,以便能够提交文件作为模型的属性。

请注意,它只能在现代浏览器中使用。它与Backbone 0.9.2一起工作,我建议检查默认的Backbone.sync并相应地采用这个想法。

function getValue (object, prop, args) { 
    if (!(object && object[prop])) return null; 
    return _.isFunction(object[prop]) ? 
    object[prop].apply(object, args) : 
    object[prop]; 
} 

var MultipartModel = Backbone.Model.extend({ 
    sync: function (method, model, options) { 
    var data 
     , methodMap = { 
      'create': 'POST', 
      'update': 'PUT', 
      'delete': 'DELETE', 
      'read': 'GET' 
     } 
     , params = { 
      type: methodMap[method], 
      dataType: 'json', 
      url: getValue(model, 'url') || this.urlError() 
     }; 

    if (method == 'create' || method == 'update') { 
     if (!!window.FormData) { 
     data = new FormData(); 
     $.each(model.toJSON(), function (name, value) { 
      if ($.isArray(value)) { 
      if (value.length > 0) { 
       $.each(value, function(index, item_value) { 
       data.append(name, item_value); 
       }) 
      } 
      } else { 
      data.append(name, value) 
      } 
     }); 
     params.contentType = false; 
     params.processData = false; 
     } else { 
     data = model.toJSON(); 
     params.contentType = "application/x-www-form-urlencoded"; 
     params.processData = true; 
     } 
     params.data = data; 
    } 

    return $.ajax(_.extend(params, options)); 
    }, 

    urlError: function() { 
    throw new Error('A "url" property or function must be specified'); 
    } 

}); 

这是从上传的观点摘录,我用<input type="file" name="file" multiple>文件上传,以便用户可以选择多个文件。然后我听取更改事件并使用collection.create上传每个文件。

var MultipartCollection = Backbone.Collection.extend({model: MultipartModel}); 


var UploadView = Backbone.View.extend({ 

    events: { 
    "change input[name=file]": "changeEvent" 
    }, 

    changeEvent: function (e) { 
    this.uploadFiles(e.target.files); 
    // Empty file input value: 
    e.target.outerHTML = e.target.outerHTML; 
    }, 

    uploadFiles: function (files) { 
    _.each(files, this.uploadFile, this); 
    return this; 
    }, 

    uploadFile: function (file) { 
    this.collection.create({file: file}); 
    return this; 
    } 

}) 
+0

我仍然感到困惑,我传入model属性以便接收文件?或者我总是必须将模型链接到表单? – Derek 2013-04-29 20:52:03

+0

我已经用我的上传处理方式更新了答案。 – 2013-04-30 06:15:34