在Django Rest框架中使用邮差上传图片时出错 [英] Error uploading image using postman in django rest framework

查看:128
本文介绍了在Django Rest框架中使用邮差上传图片时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个端点,使用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.

这是我的问题,



  1. 如何正确上传图像使用django rest框架。

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆