Django REST Framework文件上传

时间:2016-06-23 09:12:34

标签: 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"
}

这是我的模特:

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)

串行器:

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

    class Meta:
        model = Music
        fields = ('id', 'favorite', 'created_at', 'counter', 'file', 'name', 'album', 'playlist')

并查看:

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')

1 个答案:

答案 0 :(得分:6)

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

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

  

MultiPartParser
  解析multipart HTML表单内容,它支持   文件上传。 request.data将填充QueryDict

     

您通常希望同时使用FormParserMultiPartParser   一起,以完全支持HTML表单数据。

MusicViewSet中,您可以定义FormParserMultiPartParser,如果它们未在您的设置中定义,以便DRF可以解析多部分HTML表单内容。您可以使用file方法中的serializer.validated_data访问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')