Django Tastypie反序列化多部分/表单数据以上传文件 [英] Django Tastypie Deserializing Multipart/Form-Data To Upload File
问题描述
我正在尝试通过Multipart/Form-Data表单和Tastypie API上传文件,并且遇到了一些问题:
I am trying to upload files via a Multipart/Form-Data form and Tastypie API and am running into some issues:
我的模特:
class Client(models.Model):
account = models.ForeignKey(Account)
client_image = models.FileField(upload_to=client_image_path, default="/assets/img/default-user-image.png", blank=True, null=True)
client_image_thumb = models.FileField(upload_to=client_image_thumb_path, default="/assets/img/default-user-image.png", blank=True, null=True)
我正在使用Tastypie Issue#42中概述的自定义反序列化方法:
I am using a custom deserialize method as outlined in Tastypie Issue#42:
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)
def put_detail(self, request, **kwargs):
if request.META.get('CONTENT_TYPE').startswith('multipart') and \
not hasattr(request, '_body'):
request._body = ''
return super(MultipartResource, self).put_detail(request, **kwargs)
这是我对应的ModelResource:
And here is my corresponding ModelResource:
class ClientResource(MultipartResource, ModelResource):
account = fields.ForeignKey(AccountResource, 'account')
class Meta():
queryset = Client.objects.all()
always_return_data = True
resource_name = 'account/clients/client-info'
authorization = AccountLevelAuthorization()
list_allowed_methods = ['get','post','put','delete','patch']
detail_allowed_methods = ['get', 'post', 'put', 'delete','patch']
authentication = ApiKeyAuthentication()
filtering = {
'username': ALL,
}
如果我使用内容类型application/JSON进行POST,并且不包含client_image字段,它将成功创建一个新的Client Object.这表明模型/资源正在按预期方式工作.
If I do a POST with content-type application/JSON and dont include the client_image field, it will successfully create a new Client Object. This indicates that the models/resources are working as they should.
但是,当我尝试使用Multipart/Form-Data内容类型时,我可以看到它使用此有效负载正确地通过了反序列化器:
However, when I try to use a Multipart/Form-Data content type I can see that it gets through my deserializer appropriately with this payload:
------WebKitFormBoundaryp0Q7Q9djlsvVGwbb
Content-Disposition: form-data; name="{%0D%0A%22account%22"
"/api/v1/account/account-info/21/",
------WebKitFormBoundaryp0Q7Q9djlsvVGwbb
Content-Disposition: form-data; name="client_image"; filename="donavan.jpg"
Content-Type: image/jpeg
------WebKitFormBoundaryp0Q7Q9djlsvVGwbb--
我还在调试时看到此QueryDict,它正确显示了InMemoryUploadedFile:
I am also seeing this QueryDict while debugging, which shows the InMemoryUploadedFile correctly:
<QueryDict: {u'client_image': [<InMemoryUploadedFile: donavan.jpg (image/jpeg)>], u'{%0D%0A%22account%22': [u'"/api/v1/account/account-info/21/"']}>
但我不断收到此错误:
{error_message:"追踪:"Traceback(最近一次通话):文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",包装器响应中的第202行=回调(request,* args,** kwargs)文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",第440行,在dispatch_list中返回self.dispatch('list',request,** kwargs)文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",第472行,在dispatch response = method(request,** kwargs)文件中"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",第1328行,在post_list Updated_bundle = self.obj_create(bundle,** self.remove_api_resource_names(kwargs))文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",第2104行,在obj_create包= self.full_hydrate(bundle)文件中"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py",第890行,在full_hydrate值= field_object.hydrate(bundle)文件中"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/fields.py",第732行,以hydrate值= super(ToOneField,self).hydrate(bundle)文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/fields.py",第165行,在hydrif elif self.attribute和getattr(bundle.obj,self.attribute,无):文件"/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/django/db/models/fields/related.py",第343行,在 get 中,将self.field.rel.to.DoesNotExist DidNotExist提高}
{ error_message: "" traceback: "Traceback (most recent call last): File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 202, in wrapper response = callback(request, *args, **kwargs) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 440, in dispatch_list return self.dispatch('list', request, **kwargs) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 472, in dispatch response = method(request, **kwargs) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 1328, in post_list updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs)) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 2104, in obj_create bundle = self.full_hydrate(bundle) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/resources.py", line 890, in full_hydrate value = field_object.hydrate(bundle) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/fields.py", line 732, in hydrate value = super(ToOneField, self).hydrate(bundle) File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/tastypie/fields.py", line 165, in hydrate elif self.attribute and getattr(bundle.obj, self.attribute, None): File "/Users/stevewirig/Documents/www/vu/venv/lib/python2.7/site-packages/django/db/models/fields/related.py", line 343, in get raise self.field.rel.to.DoesNotExist DoesNotExist " }
有什么想法可以解决这个问题吗?提前致谢!
Any ideas where this could be broken? Thanks in advance!
推荐答案
按如下所示初始化序列化器:
Initialize the serializer as follows:
serializer =序列化器(formats = [''json'])
这篇关于Django Tastypie反序列化多部分/表单数据以上传文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!