Display image from ImageField by means of form
As Selcuk mentioned the simplest solution was to create my own widget.
from string import Template
from django.utils.safestring import mark_safe
from django.forms import ImageField
class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None, **kwargs):
html = Template("""<img src="$link"/>""")
return mark_safe(html.substitute(link=value))
class UserProfileForm(forms.ModelForm):
photo = ImageField(widget=PictureWidget)
I can't comment yet, thus I need to add this via an Answer. All credits to deathangel908 for this handy solution.
I'm using Django 2.1 and was struck with TypeError: render() got an unexpected keyword argument 'renderer'
error when trying the accepted answer. Solution to this problem can be found here: https://stackoverflow.com/a/52039655/8002464
In short, the solution must be slightly changed for Django 2.1 and upwards and include renderer=None
. Fully updated solution:
from string import Template
from django.utils.safestring import mark_safe
from django.forms ImageField
class PictureWidget(forms.widgets.Widget):
def render(self, name, value, attrs=None, renderer=None):
html = Template("""<img src="$link"/>""")
return mark_safe(html.substitute(link=value))
class UserProfileForm(forms.ModelForm):
photo = ImageField(widget=PictureWidget)
Btw. a quick small improvement, at least for my use-case was to add the media url. This way the images were actually shown instead of being lost in wrong urls. But this might only be because of how I set up my urls.
from django.conf import settings
[...]
html = Template("""<img src="$media$link"/>""")
return mark_safe(html.substitute(media=settings.MEDIA_URL, link=value))
Let me improve this interesting question. I suggest to combine image input and image preview. Subclass FileInput widget and override render to concatenate additional html to display preview image and default input image html.
from django.utils.safestring import mark_safe
from django import forms
class ImagePreviewWidget(forms.widgets.FileInput):
def render(self, name, value, attrs=None, **kwargs):
input_html = super().render(name, value, attrs=None, **kwargs)
img_html = mark_safe(f'<br><br><img src="{value.url}"/>')
return f'{input_html}{img_html}'
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = '__all__'
photo = forms.ImageField(widget=ImagePreviewWidget,)