我正在尝试使用AngularJS上传图片。
我的模型如下:
class Profile(models.Model):
user = models.OneToOneField(User)
name = models.CharField(max_length=20)
profile_picture = ImageField(upload_to=settings.MEDIA_ROOT, blank=True)
我有序列化器:
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
我有以下观点:
class ProfileViewSet(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializers
我的帖子转储就像:
name: "David"
user: 1
profile_picture: ""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…917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//U36fYf6Z697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuv/1d+n2H+meve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r/9bfp9h/pnr3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de697917r3v3Xuve/de6//Z""
但是,这对我来说是400 BAD REQUEST错误。错误消息是:
{"profile_picture":["The submitted data was not a file. Check the encoding type on the form."]}
答案 0 :(得分:3)
对应的序列化器如下:
from rest_framework import serializers
from .models import Profile
class Base64ImageField(serializers.ImageField):
def to_internal_value(self, data):
from django.core.files.base import ContentFile
import base64
import six
import uuid
if isinstance(data, six.string_types):
if 'data:' in data and ';base64,' in data:
header, data = data.split(';base64,')
try:
decoded_file = base64.b64decode(data)
except TypeError:
self.fail('invalid_image')
file_name = str(uuid.uuid4())[:12] # 12 characters are more than enough.
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
class PhotoSerializer(serializers.ModelSerializer):
profile_picture = Base64ImageField(max_length=None, use_url=True)
class Meta:
model = Profile
fields = ('profile_picture',)
答案 1 :(得分:1)
您是否为上传指定了内容类型? 'multipart / form-data'?您可能需要在视图上指定MultiPartParser以接受文件上传。
from rest_framework.parsers import JSONParser, MultiPartParser
class ProfileViewSet(viewsets.ModelViewSet):
queryset = Profile.objects.all()
serializer_class = ProfileSerializers
parser_classes = (MultiPartParser, JSONParser)
在serializers.py
中import base64
from django.core.files.base import ContentFile
from rest_framework import serializers
# From gist.github.com/yprez/7704036
class Base64ImageField(serializers.ImageField):
def from_native(self, data):
if isinstance(data, basestring) and data.startswith('data:image'):
# base64 encoded image - decode
format, imgstr = data.split(';base64,') # format ~= data:image/X,
ext = format.split('/')[-1] # guess file extension
data = ContentFile(base64.b64decode(imgstr), name='temp.' + ext)
return super(Base64ImageField, self).from_native(data)
class ProfileSerializer(serializers.ModelSerializer):
profile_picture = Base64ImageField()
class Meta:
model = Profile
fields = ('profile_picture',)