我用一个ImageField创建了一个简单的模型,我想用django-rest-framework + django-rest-swagger创建一个api视图,这是有文档记录的,并且能够上传文件。
下面是我得到的信息:
models.py
from django.utils import timezone
from django.db import models
class MyModel(models.Model):
source = models.ImageField(upload_to=u'/photos')
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(default=timezone.now)
def __unicode__(self):
return u"photo {0}".format(self.source.url)
serializer.py
from .models import MyModel
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = [
'id',
'source',
'created_at',
]
views.py
from rest_framework import generics
from .serializer import MyModelSerializer
class MyModelView(generics.CreateAPIView):
serializer_class = MyModelSerializer
parser_classes = (FileUploadParser, )
def post(self, *args, **kwargs):
"""
Create a MyModel
---
parameters:
- name: source
description: file
required: True
type: file
responseMessages:
- code: 201
message: Created
"""
return super(MyModelView, self).post(self, *args, **kwargs)
urls.py
from weddings.api.views import MyModelView
urlpatterns = patterns(
'',
url(r'^/api/mymodel/$', MyModelView.as_view()),
)
对我来说,这应该很简单。但是,我不能使上传工作。我总是得到这样的错误响应:
我已经阅读了来自django-rest-framework的这部分文档
If the view used with FileUploadParser is called with a filename URL keyword argument, then that argument will be used as the filename. If it is called without a filename URL keyword argument, then the client must set the filename in the Content-Disposition HTTP header. For example Content-Disposition: attachment; filename=upload.jpg.
然而,头部是由请求有效负载属性中的django-rest-swagger传递的(从chrome控制台)。
如果需要更多的信息,请让我知道。
我使用的是Django==1.8.8
、djangorestframework==3.3.2
和django-rest-swagger==0.3.4
。
发布于 2016-06-11 01:59:07
这是我想出的最终解决方案:
from rest_framework import generics
from rest_framework.parsers import FormParser, MultiPartParser
from .serializer import MyModelSerializer
class MyModelView(generics.CreateAPIView):
serializer_class = MyModelSerializer
parser_classes = (FormParser, MultiPartParser)
def post(self, *args, **kwargs):
"""
Create a MyModel
---
parameters:
- name: source
description: file
required: True
type: file
responseMessages:
- code: 201
message: Created
"""
return super(MyModelView, self).post(self, *args, **kwargs)
我所要做的就是将解析器从FileUploadParser
改为(FormParser, MultiPartParser)
发布于 2016-04-27 06:01:26
我通过对您的代码做了几处更改来实现这一点。
首先,在models.py
中,将ImageField
名称更改为file
,并使用相对路径上传文件夹。当您以二进制流的形式上传文件时,它在request.data
字典中的文件键(request.data.get('file')
)下可用,因此最干净的选项是将其映射到同名的模型字段。
from django.utils import timezone
from django.db import models
class MyModel(models.Model):
file = models.ImageField(upload_to=u'photos')
is_active = models.BooleanField(default=False)
created_at = models.DateTimeField(default=timezone.now)
def __unicode__(self):
return u"photo {0}".format(self.file.url)
在serializer.py
中,将源字段重命名为文件:
class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('id', 'file', 'created_at')
在views.py中,不要调用super,而是调用create():
from rest_framework import generics
from rest_framework.parsers import FileUploadParser
from .serializer import MyModelSerializer
class MyModelView(generics.CreateAPIView):
serializer_class = MyModelSerializer
parser_classes = (FileUploadParser,)
def post(self, request, *args, **kwargs):
"""
Create a MyModel
---
parameters:
- name: file
description: file
required: True
type: file
responseMessages:
- code: 201
message: Created
"""
return self.create(request, *args, **kwargs)
我已经使用Postman Chrome扩展来测试这一点。我已经将图片上传为二进制文件,并手动设置了两个头文件:
Content-Disposition: attachment; filename=upload.jpg
Content-Type: */*
发布于 2016-04-27 06:09:54
根据我的经验,FileUploadParser
使用以下格式的请求:
curl -X POST -H "Content-Type:multipart/form-data" \
-F "file=@{filename};type=image/jpg" \
https://endpoint.com/upload-uri/
视图中的request.data['file']
将包含该文件。
也许如果你尝试一个Content-Type:multipart/form-data
头,你会很幸运。
https://stackoverflow.com/questions/36701877
复制相似问题