Django fields not saving

46 Views Asked by At

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)```
1

There are 1 best solutions below

0
lustfully On

Get the image bytes first, do the process onto the bytes, and write the file bytes.

class Media(models.Model):
    file = models.FileField(upload_to="upload/")

    def save(self, *args, **kwargs):
        file_byte = self.file.read()
        file_byte_processed = your_process(file_byte)
        self.file.write(file_byte_processed)

        return super().save(*args, **kwargs)