F
F
from_rugby_to_life2022-03-15 23:16:27
Django
from_rugby_to_life, 2022-03-15 23:16:27

How to base64 encode an image when uploading it to db via django admin panel?

I need to write an api, while I already have a ready-made frontend. By assignment, I have a model that has an ImageField() field

class Recipe(models.Model):
    """Модель для управления рецептами
    """

    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='recipes',
        verbose_name='Автор рецепта',
    )
    name = models.CharField(
        max_length=200,
        verbose_name='Название рецепта',
    )
    image = models.ImageField(
        upload_to='api/images/recipes/',
        verbose_name='Картинка',
    )
    text = models.TextField(
        verbose_name='Описание рецепта',
    )
    ingredients = models.ManyToManyField(
        Ingredient,
        through='IngredientRecipe',
        through_fields=('recipe', 'ingredient'),
        verbose_name='Ингредиенты',
    )
    tags = models.ManyToManyField(
        Tag,
        related_name='recipes',
        verbose_name='Теги',
    )
    cooking_time = models.PositiveIntegerField(
        verbose_name='Время приготовления',
    )
    pub_date = models.DateTimeField(
        verbose_name='Дата публикации',
        auto_now_add=True,
    )

    def __str__(self):
        return f'{self.name}'

    class Meta:
        verbose_name = 'Рецепт'
        verbose_name_plural = 'Рецепты'
        ordering = ['-pub_date',]

By convention, when publishing a recipe, the frontend encodes the image into a base64 string; on the backend, it must be decoded and saved as a file. I made a new class in the serializer for the image field, in which I overridden the to_internal_value method :
class ImageConversion(serializers.Field):
    def to_representation(self, value):
        return value

    def to_internal_value(self, data):
        try:
            decode = BytesIO(base64.b64decode(data))
            image = Image.open(decode)
        except ValueError:
            raise serializers.ValidationError(
                'Картинка должна быть кодирована в base64'
            )
        return image

class RecipeSerializer(serializers.ModelSerializer):
    image = ImageConversion()

    class Meta:
        model = Recipe
        fields = ('id', 'author', 'name', 'image', 'text', 'ingredients',
                 'tags', 'cooking_time')

But in this form, when I upload recipes through the admin panel, and upload photos through the admin panel, api requests do not work, the following error occurs:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

As I understand it, this happens because through the admin panel I upload a photo that is not encoded in base64 to the database, and therefore, when the serializer tries to decode this image, this error is obtained. So here's the crux of the matter. If I understand the essence of the error correctly, then how can I make it so that when uploading a photo through the admin panel, it is encoded in base64? And if I understand the essence of the problem incorrectly, then tell me how can I solve this problem?

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question