我需要在django中使用tastypie修补用户个人资料图片。我使用Django 1.6,AngularJs,并且使用了Django的常规Authentication()和DjangoAuthorization()类。
当我尝试使用“内容类型:多部分/表单数据”上传图片时。我收到以下错误。
error_message: "You cannot access body after reading from request's data stream"
Firstly I know that Tastypie has no-official support for Multi-part Form-Data. I'm hoping for a monkey patch or whatever that is working until tastypie gives support for Multipart-Form Data.
I have done some research on the above and i have looked into some of the questions posted:
References:
Though the above method seemed to be like a hack.. I wanted to give it a try in my Resources.
My Resource asfollows :
class UserProfileResource(ModelResource):
user = fields.ToOneField(UserResource, 'user', full=True)
profile_img = fields.FileField(attribute="img", null=True, blank=True)
"""docstring for ProfileResource"""
def alter_list_data_to_serialize(self, request, data):
if request.GET.get('meta_only'):
return {'meta': data['meta']}
return data
def authorized_read_list(self, object_list, bundle):
return object_list.filter(user=bundle.request.user).select_related()
def obj_create(self, bundle, **kwargs):
return super(UserProfileResource, self).obj_create(bundle, user=bundle.request.user)
def dehydrate(self, bundle):
bundle.data['groups'] = [g.name for g in bundle.request.user.groups.all()]
return bundle
"""Deserialize for multipart Data"""
def deserialize(self, request, data, format=None):
if format is None:
format = request.META.get('CONTENT_TYPE','application/json')
if format == 'application/x-www-form-urlencoded':
return request.POST
elif format.startswith('multipart'):
data = request.POST.copy()
data.update(request.FILES)
return data
return super(UserProfileResource, self).deserialize(request, data, format)
"""PATCH For Making the request._body = FALSE"""
def put_detail(self, request, **kwargs):
if request.META.get('CONTENT_TYPE').startswith('multipart') and \
not hasattr(request, '_body'):
request._body = ''
return super(UserProfileResource, self).put_detail(request, **kwargs)
"""PATCH for MAKING the request._body = FALSE"""
def convert_post_to_VERB(request, verb):
"""
Force Django to process the VERB. Monkey Patch for Multipart Data
"""
if request.method == verb:
if hasattr(request, '_post'):
del (request._post)
del (request._files)
request._body # now request._body is set
request._read_started = False # so it won't cause side effects
try:
request.method = "POST"
request._load_post_and_files()
request.method = verb
except AttributeError:
request.META['REQUEST_METHOD'] = 'POST'
request._load_post_and_files()
request.META['REQUEST_METHOD'] = verb
setattr(request, verb, request.POST)
return request
class Meta:
queryset = UserProfile.objects.filter()
resource_name = 'user_profile'
list_allowed_methods = ['get', 'post']
detail_allowed_methods = ['get', 'post', 'put', 'delete', 'patch']
serializer = Serializer()
authentication = Authentication()
authorization = DjangoAuthorization()
always_return_data = True
上面的引用文献指出,方法 convert_post_to_VERB()并非旨在通过修补 request来处理Multipart数据。_read_started= False 。我们将能够使用tastypie上传文件。但是出于某种原因,即使我做了上述补丁之后,我仍然收到相同的“错误:从请求的数据流中读取后,您无法访问正文”。
请帮助我解决问题,我想念的是什么?或有没有人有一个可行的逻辑,以便我可以举一个例子。
更新:
最佳答案
您需要定义patch_detail
而不是update_detail
这是我的MultipartResource的样子:
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/form-data'):
multipart_data = request.POST.copy()
multipart_data.update(request.FILES)
return multipart_data
return super(MultipartResource, self).deserialize(request, data, format)
def put_detail(self, request, **kwargs):
if request.META.get('CONTENT_TYPE', '').startswith('multipart/form-data') and not hasattr(request, '_body'):
request._body = ''
return super(MultipartResource, self).put_detail(request, **kwargs)
def patch_detail(self, request, **kwargs):
if request.META.get('CONTENT_TYPE', '').startswith('multipart/form-data') and not hasattr(request, '_body'):
request._body = ''
return super(MultipartResource, self).patch_detail(request, **kwargs)
我在资源上通过ModelResource将其与多继承一起使用:
class MyResource(MultipartResource, ModelResource):
pass
顺便说一句,没有必要为资源设置
convert_post_to_VERB
方法。不幸的是,在stylishpie的Resource类中,这不是可以覆盖的方法。他们在resource.py模块中将其定义为函数。关于python - Django-Tastypie中的多部分/表单数据POST,PUT,PATCH,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25182131/