以 form 的方式显示来自 ImageField 的图片
Display image from ImageField by means of form
序曲:
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。所以我想要请假 template.html 如下所示。
template.html
<table>
{{ form.as_table }}
</table>
并添加到 models.py 一个 image_tag
方法:
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)
我得到一个错误 Unknown field(s) (image_tag) specified for UserProfile
这是公平的。
我也试过将它放在 readonly_fields
中,但它们不显示。我必须创建 list_view 吗?如果是的话应该在哪里?
我在这里想念什么?为什么 image_tag
方法应该是模型的一部分而不是表单的一部分?模型描述了数据应该如何保存在数据库中,而不是它应该如何通过表单呈现给用户。这应该是表格的一部分,不是吗?如果我错了,请纠正我。我该如何解决这个问题?任何帮助将不胜感激!
如 Selcuk 所述,最简单的解决方案是创建我自己的小部件。
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)
我还不能发表评论,因此我需要通过回答来添加。这个方便的解决方案的所有功劳都归功于 deathangel908。
我使用的是 Django 2.1,在尝试接受的答案时遇到 TypeError: render() got an unexpected keyword argument 'renderer'
错误。可以在此处找到此问题的解决方案:
简而言之,解决方案必须针对 Django 2.1 及更高版本稍作更改并包含 renderer=None
。完全更新的解决方案:
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)
顺便说一句。一个快速的小改进,至少对于我的用例来说是添加媒体 url。这样,图像就会真正显示出来,而不是在错误的 url 中丢失。但这可能只是因为我如何设置 urls.
from django.conf import settings
[...]
html = Template("""<img src="$media$link"/>""")
return mark_safe(html.substitute(media=settings.MEDIA_URL, link=value))
让我改进这个有趣的问题。我建议结合图像输入和图像预览。将 FileInput 小部件子类化并覆盖渲染以连接其他 html 以显示预览图像和默认输入图像 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,)
from django.utils.safestring import mark_safe
class ImagePreviewWidget(forms.widgets.FileInput):
def render(self, name, value, attrs=None, **kwargs):
input_html = super().render(name, value, attrs=None, **kwargs)
if value:
img_html = mark_safe(
f'<br><br><img src="{value.url}" width="200" />')
return f'{input_html}{img_html}'
return input_html
如果您想使用相同的表单来创建和更新,我建议您稍作改动。 if 条件将检查值是否存在“是一个更新表单”,否则只给你输入字段。
序曲:
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。所以我想要请假 template.html 如下所示。
template.html
<table>
{{ form.as_table }}
</table>
并添加到 models.py 一个 image_tag
方法:
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)
我得到一个错误 Unknown field(s) (image_tag) specified for UserProfile
这是公平的。
我也试过将它放在 readonly_fields
中,但它们不显示。我必须创建 list_view 吗?如果是的话应该在哪里?
我在这里想念什么?为什么 image_tag
方法应该是模型的一部分而不是表单的一部分?模型描述了数据应该如何保存在数据库中,而不是它应该如何通过表单呈现给用户。这应该是表格的一部分,不是吗?如果我错了,请纠正我。我该如何解决这个问题?任何帮助将不胜感激!
如 Selcuk 所述,最简单的解决方案是创建我自己的小部件。
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)
我还不能发表评论,因此我需要通过回答来添加。这个方便的解决方案的所有功劳都归功于 deathangel908。
我使用的是 Django 2.1,在尝试接受的答案时遇到 TypeError: render() got an unexpected keyword argument 'renderer'
错误。可以在此处找到此问题的解决方案:
简而言之,解决方案必须针对 Django 2.1 及更高版本稍作更改并包含 renderer=None
。完全更新的解决方案:
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)
顺便说一句。一个快速的小改进,至少对于我的用例来说是添加媒体 url。这样,图像就会真正显示出来,而不是在错误的 url 中丢失。但这可能只是因为我如何设置 urls.
from django.conf import settings
[...]
html = Template("""<img src="$media$link"/>""")
return mark_safe(html.substitute(media=settings.MEDIA_URL, link=value))
让我改进这个有趣的问题。我建议结合图像输入和图像预览。将 FileInput 小部件子类化并覆盖渲染以连接其他 html 以显示预览图像和默认输入图像 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,)
from django.utils.safestring import mark_safe
class ImagePreviewWidget(forms.widgets.FileInput):
def render(self, name, value, attrs=None, **kwargs):
input_html = super().render(name, value, attrs=None, **kwargs)
if value:
img_html = mark_safe(
f'<br><br><img src="{value.url}" width="200" />')
return f'{input_html}{img_html}'
return input_html
如果您想使用相同的表单来创建和更新,我建议您稍作改动。 if 条件将检查值是否存在“是一个更新表单”,否则只给你输入字段。