在Django Rest框架中使用邮差上传图片时出错 [英] Error uploading image using postman in django rest framework
问题描述
我正在尝试创建一个端点,使用django rest框架将图像(使用邮递员)上传到特定文件夹。这是我对文件夹的设置,
I'm trying to create an endpoint to upload images(using postman) to a specific folder using django rest framework. This is my settings for the folder,
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
这是我的模型,
class UserMedia(models.Model):
user = models.OneToOneField(User, related_name='medias', on_delete=models.CASCADE, )
profile_image_web = models.FileField(null=True)
profile_image_android = models.FileField(null=True)
profile_image_ios = models.FileField(null=True)
thumbnail = models.FileField(null=True)
这是序列化程序,
class UserMediaSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserMedia
fields = (
'profile_image_web', 'profile_image_ios', 'profile_image_android', 'thumbnail',
)
api,
class CreateUpdateUserMedia(views.APIView):
parser_classes = (MultiPartParser, FormParser)
def post(self, request, **kwargs):
serializer = UserMediaSerializer(request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
现在当我尝试上载一个对应于一个的图像时
Now when I try to upload ONE image corresponding to one of the fields using POSTMAN, this is the error I get.
'Cannot call `.is_valid()` as no `data=` keyword argument was '
AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance.
这是完全可以理解的,但我不知道如何解决。
Which is perfectly understandable, but I dont know how to fix it.
这是我的问题,
-
如何正确上传图像使用django rest框架。
How do I correctly upload images using django rest framework.
我不希望将此api与4个图像一起调用,而是一次使用4个图像调用4次,如何
I don't expect this api to be called with 4 images together, but 4 times using one image at a time, how do I pass the relevant name and modify the serializer accordingly.
如何提供根媒体目录的子路径。
How do I provide a subpath to the root media directory.
最后,我希望序列化程序显示完整的图像URL,该怎么办?
Finally I want the serializer to display the full image url, how do I do that?
推荐答案
您正在使用 serializer = UserMediaSerializer(request.data)
,但您应通过 serializer = UserMediaSerializer(data = request.data)
You are using serializer = UserMediaSerializer(request.data)
but you should call it by serializer = UserMediaSerializer(data=request.data)
来调用它,以便在Django中上传图像其余框架,您应该在S3上上传图像并通过s3 u DRF API中的rl或在序列化程序中使用base64字段,并在API中发送图像的base64编码值
For uploading images in Django rest framework you should either upload images on S3 and pass s3 url in DRF API or use base64 field in serializer and send base64 encoded value of image in API
import uuid
import base64
import imghdr
from django.utils.translation import ugettext_lazy as _
from django.core.files.base import ContentFile
from rest_framework import serializers
ALLOWED_IMAGE_TYPES = (
"jpeg",
"jpg",
"png",
"gif"
)
class Base64ImageField(serializers.ImageField):
"""
A django-rest-framework field for handling image-uploads through raw post data.
It uses base64 for en-/decoding the contents of the file.
"""
def to_internal_value(self, base64_data):
# Check if this is a base64 string
if not base64_data:
return None
if isinstance(base64_data, basestring):
# Try to decode the file. Return validation error if it fails.
try:
decoded_file = base64.b64decode(base64_data)
except TypeError:
raise serializers.ValidationError(_("Please upload a valid 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)
if file_extension not in ALLOWED_IMAGE_TYPES:
raise serializers.ValidationError(_("The type of the image couldn't been determined."))
complete_file_name = file_name + "." + file_extension
data = ContentFile(decoded_file, name=complete_file_name)
return super(Base64ImageField, self).to_internal_value(data)
raise serializers.ValidationError('This is not an base64 string')
def to_representation(self, value):
# Return url including domain name.
return value.name
def get_file_extension(self, filename, decoded_file):
extension = imghdr.what(filename, decoded_file)
extension = "jpg" if extension == "jpeg" else extension
return extension
已更新
您应该对图像使用ImageField(而不是FileField)。
You should use ImageField (not FileField) for images.
您可以像其他任何字段一样直接在序列化程序中使用以上字段。
You can use above field directly in serializer like any other field.
class UserMediaSerializer(serializers.ModelSerializer):
profile_image_web = Base64ImageField(required=False)
class Meta:
model = models.UserMedia
fields = ('profile_image_web', 'profile_image_ios', 'profile_image_android', 'thumbnail')
这篇关于在Django Rest框架中使用邮差上传图片时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!