Django REST Framework文件上传

pyp*_*ism 4 django django-rest-framework

我正在尝试使用一些表单数据上传文件.为了测试我的api,我使用Postman.当我尝试使用文件和其他字段进行POST时,我收到了此错误

{
  "detail": "JSON parse error - 'utf-8' codec can't decode byte 0xbf in position 10: invalid start byte"
}
Run Code Online (Sandbox Code Playgroud)

这是我的模型:

class Music(models.Model):
    album = models.ForeignKey(Album, related_name='tracks')
    playlist = models.ForeignKey(Playlist, null=True, related_name='tracks')
    name = models.CharField(max_length=200, unique=True)
    dropbox_id = models.CharField(max_length=500, null=True)
    favorite = models.BooleanField(default=False)
    created_at = models.DateField(auto_now_add=True)
    counter = models.IntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)

串行:

class MusicSerializer(serializers.ModelSerializer):
    file = serializers.FileField(required=True)

    class Meta:
        model = Music
        fields = ('id', 'favorite', 'created_at', 'counter', 'file', 'name', 'album', 'playlist')
Run Code Online (Sandbox Code Playgroud)

并查看:

class MusicViewSet(viewsets.ModelViewSet):
    queryset = Music.objects.all()
    serializer_class = MusicSerializer

    def perform_create(self, serializer):
        file_obj = self.request.FILES['file']
        dbx = dropbox.Dropbox(JSON_DATA['dropbox_access_token'])
        res = dbx.files_upload(file_obj, '/', autorename=True, mute=True)
        print(res)
        serializer.save(dropbox_id='x')
Run Code Online (Sandbox Code Playgroud)

Rah*_*pta 7

您无法上传包含JSON请求内容的文件.

您应该使用multipart/form-data内容发送数据.DRF MultiPartParser处理支持文件上传的多部分HTML表单内容.

MultiPartParser
解析multipartHTML表单内容,支持文件上载.两者都request.data将填充一个QueryDict.

您通常希望同时使用它们FormParser,MultiPartParser 以便完全支持HTML表单数据.

在你的MusicViewSet,你可以定义FormParserMultiPartParser,如果他们不能在你的设置中定义,这样DRF可以解析到多HTML表单的内容.您可以访问fileusing serializer.validated_datain perform_create()方法.

class MusicViewSet(viewsets.ModelViewSet):
    queryset = Music.objects.all()
    serializer_class = MusicSerializer
    parser_classes = (FormParser, MultiPartParser) # set parsers if not set in settings. Edited

    def perform_create(self, serializer):
        file_obj = self.validated_data['file'] # access file
        dbx = dropbox.Dropbox(JSON_DATA['dropbox_access_token'])
        res = dbx.files_upload(file_obj, '/', autorename=True, mute=True)
        serializer.save(dropbox_id='x')
Run Code Online (Sandbox Code Playgroud)

  • 使用邮递员,您只需选择"表单数据"选项,而无需添加内容类型标题.你应该在那里添加文件和其他键. (2认同)