Django REST Framework上传图片:“提交的数据不是文件”
正在研究如何在Django中上传文件,在这里我遇到了一个不容易理解的问题,并出现了以下错误:
提交的数据不是文件。检查表单上的编码类型。
下面是详细信息。
注意:我还查看了Django Rest Framework ImageField,并尝试了
serializer = ImageSerializer(data=request.data, files=request.FILES)
但我明白了
TypeError:()得到了意外的关键字参数“文件”
我有一个Image
要通过Django REST框架与之交互的模型:
models.py
class Image(models.Model): image = models.ImageField(upload_to='item_images')
owner = models.ForeignKey(
User, related_name='uploaded_item_images',
blank=False,
)
time_created = models.DateTimeField(auto_now_add=True)
serializers.py
class ImageSerializer(serializers.ModelSerializer): image = serializers.ImageField(
max_length=None, use_url=True,
)
class Meta:
model = Image
fields = ("id", 'image', 'owner', 'time_created', )
settings.py
'DEFAULT_PARSER_CLASSES': ( 'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
),
前端(使用AngularJS和angular-restmod或$resource)JSON以owner和image形式发送数据:
输入:
{"owner": 5, "image": "data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0A..."}
在后端,request.data显示
{u'owner': 5, u'image': u'data:image/jpeg;base64,/9j/4QqdRXhpZgAATU0AKgAAA..."}
但随后ImageSerializer(data=request.data).errors显示错误
ReturnDict([('image', [u'The submitted data was not a file. Check the encoding type on the form.'])])
我想知道该如何解决该错误?
编辑:JS部分
相关的前端代码由两部分组成:a angular-file-dnd directive
(在此处可用)将文件拖放到页面上,和angular-restmod
提供CRUD操作:
<!-- The template: according to angular-file-dnd, --><!-- it will store the dropped image into variable $scope.image -->
<div file-dropzone="[image/png, image/jpeg, image/gif]" file="image" class='method' data-max-file-size="3" file-name="imageFileName">
<div layout='row' layout-align='center'>
<i class="fa fa-upload" style='font-size:50px;'></i>
</div>
<div class='text-large'>Drap & drop your photo here</div>
</div>
# A simple `Image` `model` to perform `POST`
$scope.image_resource = Image.$build();
$scope.upload = function() {
console.log("uploading");
$scope.image_resource.image = $scope.image;
$scope.image_resource.owner = Auth.get_profile().user_id;
return $scope.image_resource.$save();
};
关于该问题的更新:现在我切换到using ng-file-upload
,它以正确的格式发送图像数据。
回答:
你遇到的问题是Django REST框架希望通过标准文件上传方法将文件作为多部分表单数据上传。这通常是一个file字段,但是JavaScript Blob对象也适用于AJAX。
你正在寻找使用base64编码的字符串而非原始文件(默认情况下不支持)上传文件。那里有a的Base64ImageField实现,但是最有前途的是pull请求。
由于这些文件主要是为Django REST框架2.x设计的,因此我对pull请求中的一个文件进行了改进,并创建了一个应与DRF 3兼容的文件。
serializers.py
from rest_framework import serializers class Base64ImageField(serializers.ImageField):
"""
A Django REST framework field for handling image-uploads through raw post data.
It uses base64 for encoding and decoding the contents of the file.
Heavily based on
https://github.com/tomchristie/django-rest-framework/pull/1268
Updated for Django REST framework 3.
"""
def to_internal_value(self, data):
from django.core.files.base import ContentFile
import base64
import six
import uuid
# Check if this is a base64 string
if isinstance(data, six.string_types):
# Check if the base64 string is in the "data:" format
if 'data:' in data and ';base64,' in data:
# Break out the header from the base64 content
header, data = data.split(';base64,')
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(data)
except TypeError:
self.fail('invalid_image')
# Generate file name:
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
# Get the file name extension:
file_extension = self.get_file_extension(file_name, decoded_file)
complete_file_name = "%s.%s" % (file_name, file_extension, )
data = ContentFile(decoded_file, name=complete_file_name)
return super(Base64ImageField, self).to_internal_value(data)
def get_file_extension(self, file_name, decoded_file):
import imghdr
extension = imghdr.what(file_name, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
应该用它代替ImageField
Django REST框架提供的标准。所以你的序列化器会变成
class ImageSerializer(serializers.ModelSerializer): image = Base64ImageField(
max_length=None, use_url=True,
)
class Meta:
model = Image
fields = ("id", 'image', 'owner', 'time_created', )
这应该允许你指定base64编码的字符串,或者指定BlobDjango REST框架通常期望的标准对象。
以上是 Django REST Framework上传图片:“提交的数据不是文件” 的全部内容, 来源链接: utcz.com/qa/430013.html