如何通过 PUT 在 Django DRF 中测试 mp3 上传?

How to test mp3 upload in Django DRF, via PUT?

我尝试测试 mp3 修改(因此 PUT)。到目前为止我有以下内容:

client = Client()
with open('my_modified_audio.mp3', 'rb') as fp:
    response = client.put(
            f"/resource/{resource_id}/",
            data={'audio': fp})

但是,我得到 response.status_code == 415 因为 DRF 的 ModelViewSet 中的序列化器行
serializer = self.get_serializer(instance, data=request.data, partial=partial).
失败
rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.

我试过设置 format="multipart",将内容类型设置为 json 或表单编码,目前没有任何帮助。资源模型使用 FileField:

class Resource(models.Model):
    audio = models.FileField(upload_to='uploads')

我怎样才能让这个 put 请求生效?

我认为以下方法可行:

客户:

import requests
...

client = Client()
files = [('audio': open('my_modified_audio.mp3', 'rb'))]
url = f"/resource/{resource_id}/"

# response = client.put(url, data=None, files=files)
# You can test it using the `requests` instead of Client()
response = requests.put(url, data=None, files=files)

序列化程序:

class AudioSerializer(serializers.Serializer):
    """ AudioSerializer """
    audio = serializers.FileField(...)

    def create(self, validated_data):
        ...

    def update(self, instance, validated_data):
        ...

观点:

from rest_framework.generics import UpdateAPIView

class AudioView(UpdateAPIView):
   ...
   parser_classes = (FormParser, MultiPartParser)
   serializer_class = AudioSerializer
   ...

受@athansp回答的启发,我比较了client.postclient.put的源代码,结果发现put的实现与post略有不同,因此是一种可行的提交方式带 put 的文件是:

from django.test.client import MULTIPART_CONTENT, encode_multipart, BOUNDARY

client = Client()
with open('my_modified_audio.mp3', 'rb') as fp:
    response = client.put(
        f"/resource/{resource_id}/",
        data=encode_multipart(BOUNDARY, {
            'other_field': 'some other data',
            'audio': fp,
        }),
        content_type=MULTIPART_CONTENT
    )

哈哈。