2013-04-29 56 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