Python Django Rest框架-如何使用序列化程序以JPEG格式导入图像并将其保存为base 64?

Python Django Rest框架-如何使用序列化程序以JPEG格式导入图像并将其保存为base 64?,python,django,django-models,django-rest-framework,Python,Django,Django Models,Django Rest Framework,型号: 序列化程序: class Item(models.Model): class Meta: db_table = 't_item' item_name = models.CharField(max_length=200) image = models.ImageField(upload_to='item_images') created_at = models.DateTimeField(default=datetime.now, blank=Tr

型号:

序列化程序:

class Item(models.Model):

   class Meta:
       db_table = 't_item'

   item_name = models.CharField(max_length=200)
   image = models.ImageField(upload_to='item_images')
   created_at = models.DateTimeField(default=datetime.now, blank=True)
   updated_at = models.DateTimeField(default=datetime.now, blank=True)

   def __str__(self):
       return self.item_name
在web视图表单中,我希望导入JPEG格式的图像,在发布时,我希望将其保存为Base 64格式,保存在“upload_to”中指定的位置。这可能吗

编写模型保存功能,访问上传的图片 然后将其编码为base64并保存到不可编辑的base64图像字段

你可以试试这个

在serailizer.py中

import os
import base64

def image_as_base64(image_file, format='png'):
    """
    :param `image_file` for the complete path of image.
    :param `format` is format for image, eg: `png` or `jpg`.
    """
    if not os.path.isfile(image_file):
        return None

    encoded_string = ''
    with open(image_file, 'rb') as img_f:
        encoded_string = base64.b64encode(img_f.read())
    return 'data:image/%s;base64,%s' % (format, encoded_string)


# Example Usage

from django import models
from django.conf import settings

class Post(models.Model):

    cover = models.ImageField(upload_to='images/%Y/%m/%d')

    def get_cover_base64(self):
        # settings.MEDIA_ROOT = '/path/to/env/projectname/media'
        return image_as_base64(settings.MEDIA_ROOT + self.cover.path)
在api视图中

class Base64ImageField(serializers.ImageField):

    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

class ItemSerializer(serializers.ModelSerializer):
   image = Base64ImageField(required=True)

希望有帮助

是的,您可以在视图中覆盖模型的保存方式,或者在模型中覆盖保存方法。但你为什么要这么做?保存模型时,图像将自动保存为jpeg文件。如果您希望图像也以不同的格式保存,可以挂接到模型的post_save信号并创建base64文件。我想将其保存为base 64而不是JPEG,这样在文件大小方面会更有效。如果您有,请使用docx链接对您的答案进行描述。抱歉,这里是详细信息。您还应该将原始参数传递给super.save方法。使用**kwargs会更容易。我遇到了一个错误:调用Item.objects.create时遇到了TypeError。这可能是因为序列化程序类上的可写字段不是Item.objects.create的有效参数。您可能需要将该字段设置为只读,或重写ItemSerializer.create方法以正确处理此问题。您可以将该base64映像保存到不同的字段。
class Base64ImageField(serializers.ImageField):

    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

class ItemSerializer(serializers.ModelSerializer):
   image = Base64ImageField(required=True)
class ImageSave(APIView):
   serializer_class = ItemSerializer
   def post(self):
      serializer_instance = 
      self.serializer_class(data=self.request.data)

      if serializer_instance.is_valid():
         serializer_instance.save()

      return Response({})