pythondjangodjango-2.2

django admin: save image like base64


I'd like to upload image through django admin panel, but I need to save it as a base64 string in database How could I do it? +

  1. I would like to see image in admin
  2. DB may move someday and it will be better to save just base64 string, so I won't depend on some file structure (as if I'll store original images somewhere)

ps. I have django 2.2.6 version


Solution

  • It is considered a bad practice to save images in the database, you're much better off using django-storages and saving the images to some external S3-compatible storage service.

    If you insist on your approach: To be able to upload images through the Django admin and have them stored as base64 you would need a save method in your model that encodes your image to b64 and saves the data in a field. Something like:

    import base64
    
    
    class Image(models.Model):
        ...
        image_file = models.ImageField(upload_to='images/', default='blank.jpg')
        image_b64 = models.BinaryField(blank=True, null=True)
    
        def save(self, *args, **kwargs):
            if self.image_file:
                img_file = open(self.image_file.url, "rb")
                self.image_b64 = base64.b64encode(img_file.read())
                super(Image, self).save(*args, **kwargs)
    

    You could display the ImageField on your Admin, remove the Base64 field via admin.py. If you want to display it in the Admin from the Base64 field then you could save it as a html string adding tags (also set the field up with an image widget in your admin.py to display it). Model could be something like:

    class Image(models.Model):
        ...
        image_file = models.ImageField(upload_to='images/', default='blank.jpg')
        image_b64 = models.TextField(blank=True)
    
        def save(self, *args, **kwargs):
            if self.image_file:
                img_file = open(self.image_file.url, "rb")
                data = base64.b64encode(img_file.read())
                self.image_b64 = format_html('<img src="data:;base64,{}">', data)
                super(Image, self).save(*args, **kwargs)