Uploading files to tastypie with Backbone?

我的梦境 提交于 2019-12-21 02:58:06

问题


Checked some other questions and I think my tastypie resource should look something like this:

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

Please tell me if that's wrong.

What I don't get, assuming the above is correct, is what to pass to the resource. Here is a file input:

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

If I have a backbone model img what do I set image to?

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'" ...

What do I set my backbone "image" attribute to so that I can upload a file to tastypie via ajax?


回答1:


You may override sync method to serialize with FormData api to be able to submit files as model's attributes.

Please note that it will work only in modern browsers. It worked with Backbone 0.9.2, I advise to check the default Backbone.sync and adopt the idea accordingly.

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');
  }

});

This is excerpt from upload view, I use <input type="file" name="file" multiple> for file uploads so user can select many files. I then listen to the change event and use collection.create to upload each file.

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;
  }

})


来源:https://stackoverflow.com/questions/16274241/uploading-files-to-tastypie-with-backbone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!