I want to receive a file from the client and perform some processing on the image in the corresponding model class before it is saved in the database. However, since the file is not saved until the end of the save() method, the directory where the file is stored is not created and I get the error FileNotFoundError: [Errno 2] No such file or directory: 'media/upload/vertical_image.jpg'.
I'm actually looking for a way to do all the processing in the save method
this is my Media model:
class Media(models.Model):
title = models.CharField(max_length=255, null=True, blank=True)
file = models.FileField(upload_to="upload/")
filename = models.CharField(max_length=255, null=True, blank=True)
mime_type = models.CharField(max_length=255, null=True, blank=True)
thumbnail = models.JSONField(null=True, blank=True)
size = models.FloatField(null=True, blank=True)
url = models.CharField(max_length=300, null=True, blank=True)
thumbhash = models.CharField(max_length=255, blank=True, null=True)
is_public = models.BooleanField(blank=True, null=True)
def save(self, *args, **kwargs):
sizes = [(150, 150), (256, 256)]
media_path = f"media/upload/{self.filename}"
image = Image.open(media_path)
mime_type = image.get_format_mimetype()
format = mime_type.split("/")[1]
if not os.path.exists("media/cache"):
os.makedirs("media/cache")
thumbnail = {}
for i, size in enumerate(sizes):
resized_image = image.resize(size)
index = "small" if i == 0 else "medium"
file_path = os.path.join(
"media",
"cache",
f"{self.id}-resized-{self.filename}-{index}.{format}",
)
resized_image.save(file_path, format=format)
thumbnail["*".join(str(i) for i in size)] = file_path
self.mime_type = mime_type
self.size = os.path.getsize(media_path)
self.thumbnail = thumbnail
self.url = f"http://127.0.0.1:8000/media/upload/{self.filename}"
self.thumbhash = image_to_thumbhash(image)
super().save(*args, **kwargs)
and this is my media serializer:
class MediaSerializer(serializers.ModelSerializer):
class Meta:
model = Media
fields = [
"id",
"title",
"file",
"filename",
]
def create(self, validated_data):
return Media(**validated_data)```
Get the image bytes first, do the process onto the bytes, and write the file bytes.