检查了一些其他问题,我认为我的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?
答案 0 :(得分: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;
}
})