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({})