I've got web project with Django backend for which I decided to store images as BinaryField, it seemed to be more convenient for me in case of making backups and restoring them.
At first I've created model:
class ThermalSource(ClusterUnit):
    ...
    scheme_image = models.BinaryField(verbose_name='Scheme', blank=True, null=True, editable=True)
    ...
Then created serializer to use in viewset (I know it is not related to admin interface, but maybe it will be useful):
class Base64BinaryField(serializers.Field):
    def to_representation(self, value):
        from base64 import b64encode
        return b64encode(value)
    def to_internal_value(self, data):
        from base64 import b64decode
        return b64decode(data)
class ThermalSourceSerializer(APAMModelSerializer):
    ...
    scheme_image_base64 = Base64BinaryField(source='scheme_image')
    ...
Now I could get and set images converted to Base64 correctly via Django REST Framework.
Admin class for ThermalSource looks so now:
class ThermalSourceForm(forms.ModelForm):
    scheme_image = forms.FileField(required=False)
    def save(self, commit=True):
        if self.cleaned_data.get('scheme_image') is not None \
                and hasattr(self.cleaned_data['scheme_image'], 'file'):
            data = self.cleaned_data['scheme_image'].file.read()
            self.instance.scheme_image = data
        return self.instance
    def save_m2m(self):
        # FIXME: this function is required by ModelAdmin, otherwise save process will fail
        pass
class ThermalSourceAdmin(admin.ModelAdmin):
    form = ThermalSourceForm
    readonly_fields = ('id', )
    list_display = ('id', ... 'scheme_image')
But when I open Django admin interface, I could only download files to scheme image field, no preview is configured.
Could anybody suggest me how could I configure admin class for my model to be able to see images previews in Django admin interface?
Fist, add the code below to your model.
def scheme_image_tag(self):
    from base64 import b64encode
    return mark_safe('<img src = "data: image/png; base64, {}" width="200" height="100">'.format(
        b64encode(self.scheme_image).decode('utf8')
    ))
scheme_image_tag.short_description = 'Image'
scheme_image_tag.allow_tags = True
Then, you can render this field on your list_display (admin).
list_display = (...'scheme_image_tag')
As mentioned by @DmitriyVinokurov, you can add this tag to readonly_fields.
readonly_fields = (..., 'scheme_image_tag')
P.S. This answer explains why I'm using decode('utf8').
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With