【问题标题】:How patch resource with file如何用文件修补资源
【发布时间】:2016-06-17 21:33:32
【问题描述】:

我有这个模型和资源用于用户配置文件

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

【问题讨论】:

    标签: python django api rest tastypie


    【解决方案1】:

    这是 DRF(django-rest-framework) 中的问题之一,您可以在 Tom Christie 的 GitHub 上查看。问题已通过下面给出的解决方案关闭。您还可以在djang-rest-framework 存储库的issues 页面上找到相同的解决方案

    由于各种原因,Django 只允许读取一次 POST 正文。由于正文是通过类似文件的 API 公开的,因此您不能轻松地再次读取该文件。此外,如果您已读取数据,您将无法更改上传文件处理程序。仅读取一次 POST 数据失败会失败,调试起来很棘手,原因有两个。

    • Django 仅在您第二次访问正文时报告其错误,所以 第一次访问它可能很难跟踪。
    • 许多不同的问题都可能导致此问题。一种方法是打印 完整回溯(每当数据获取时使用traceback.print_stack()) 阅读(在django/http/request.py:HttpRequest.read 和 HttpRequest.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 确实是 POST 并且确实使用了 Content-Type 在表单提交时发送。

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

    禁用浏览器覆盖

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

    在 Django 测试客户端中更改 Content-Type

     from django.test import Client
    
     client = Client()
     response = client.post(url, content_type='application/json')
    

    【讨论】:

      【解决方案2】:

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

      查看此Github issue,了解有关如何将 POST(或 PATCH)文件发送到资源的更多信息。

      另外,这个stack 与你的问题有关。

      【讨论】:

      • 谢谢!这是一个绝妙的解决方案!
      猜你喜欢
      • 2021-12-23
      • 2018-11-18
      • 2021-05-22
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      相关资源
      最近更新 更多