Display image from ImageField by means of form

十年热恋 提交于 2020-01-23 09:58:17

问题


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 template.html just to check if it's an imageField and display it in a different way. I want to handle it via form or widget or something like this. So I want the leave template.html as it's bellow.

template.html

<table>
    {{ form.as_table }}
</table>

And add to models.py an image_tag method:

class UserProfile(Model):
  photo = ImageField(upload_to=PHOTO_DIRECTORY)
  contacts = TextField(null=True)
  ... others

  def image_tag(self):
    return u'<img src="%s" />' % self.photo.url

  image_tag.short_description = 'Image'
  image_tag.allow_tags = True

forms.py:

class UserProfileForm(forms.ModelForm):

  class Meta:
    model = UserProfile
    fields = ('contacts', 'photo', 'image_tag', ...others)

I get an error that Unknown field(s) (image_tag) specified for UserProfile which is fair enought.

I also tried to place it in readonly_fields but they don't display somehow. Do I have to create list_view? If yes where should it be?

What do I miss here? Why the image_tag method should be a part of model instead of form? Model describes how data should persists in the database, not how it should present to user via form. This should be a part of form, shouldn't it?. Correct me please if I'm wrong. How do I solve the issue? Any help would be greatly appreciated!


回答1:


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)



回答2:


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


来源:https://stackoverflow.com/questions/28764571/display-image-from-imagefield-by-means-of-form

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!