如何用文件修补资源

How patch resource with file

我有用户配置文件的模型和资源

class Profile(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(blank=False, null=False, unique=True)
    avatar = models.ImageField(blank=True, null=True)

class ProfileResource(ModelResource):
    class Meta:
        queryset = Profile.objects.all()
        resource_name = 'profiles'
        allowed_methods = ['get', 'patch']

当我尝试修补此资源时,出现异常:

RawPostDataException("You cannot access body after reading from request's data stream")

为了发送测试数据,我使用 chrome-extention

It was one of the issues in DRF(django-rest-framework) you can check on GitHub of Tom Christie. Issue was closed with the solution given below. You can also find same solution on issues page of djang-rest-framework repository

由于各种原因,Django 只允许读取 POST 主体一次。由于 body 暴露在类似文件 API 中,因此您无法轻松再次读取该文件。此外,如果您已经读取了数据,您将无法更改上传文件处理程序。只读取一次POST数据就会失败,调试起来比较棘手,原因有二。

  • Django 仅在您第二次访问正文时报告其错误,因此 第一次访问时可能很难跟踪。
  • 无数不同的问题都可能导致这种情况。一种方法是打印 完整的回溯(使用 traceback.print_stack()) 每当数据获取 阅读(在 django/http/request.py: HttpRequest.readHttpRequest.readline)。我是这样做的,也许还有其他的 方式。

那么,您是否在代码中的某处访问了 request.method?你在使用 Django 测试客户端吗?如果是这样,则可能是 HTTP header based method overriding 启动了。此功能允许浏览器模拟 GET/POST 以外的请求。为此,django-rest-framework 查看隐藏的表单字段,例如 <input type="hidden" name="_method" value="DELETE">。对于 POST 请求,此信息位于请求正文中,因此 django-rest-framework 必须读取请求正文。

此功能是 enabled by default, 但 django-rest-framework 确保

request is indeed POST and is indeed using a Content-Type that would be sent on a form submission.

但这正是 Django test client! 的行为 存在两个可能的修复方法:

禁用浏览器覆盖

REST_FRAMEWORK = {
'FORM_METHOD_OVERRIDE': None,
'FORM_CONTENT_OVERRIDE': None,
'FORM_CONTENTTYPE_OVERRIDE': None
 }

更改 Django 测试客户端中的内容类型

 from django.test import Client

 client = Client()
 response = client.post(url, content_type='application/json')

这与您尝试进行的文件上传有关。无法以这种方式处理内容类型,您应该将文件转换为 base64 才能执行此操作。

查看此 Github issue 以获取有关如何继续将 POST(或 PATCH)文件添加到您的资源的更多信息。

此外,这个stack与您的问题有关。