Dmitrii Vinokurov
Dmitrii Vinokurov

Reputation: 395

How to show BinaryField image preview in Django admin interface?

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?

Upvotes: 4

Views: 2860

Answers (1)

Eliakin Costa
Eliakin Costa

Reputation: 960

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').

Upvotes: 7

Related Questions