Display image from ImageField by means of form

前端 未结 3 1231
猫巷女王i
猫巷女王i 2021-01-05 07:18

prelude:

Here\'s the simpliest way to display an ImageField. Lets assume I have 10 fields in my form and I don\'t wanna iterate over all of them in

相关标签:
3条回答
  • 2021-01-05 07:31

    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,)
    
    0 讨论(0)
  • 2021-01-05 07:44

    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))
    
    0 讨论(0)
  • 2021-01-05 07:47

    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)
    
    0 讨论(0)
提交回复
热议问题