Django Admin从Imagefield显示图像
虽然我可以在list_display中显示上传的图像,但是可以在每个模型页面上执行此操作(就像在更改模型的页面中一样)?
一个快速样本模型将是:
Class Model1(models.Model): image = models.ImageField(upload_to=directory)
默认pipe理员显示上传图像的url,但不显示图像本身。
谢谢!
当然。 在您的模型类中添加一个方法,如:
def image_tag(self): return u'<img src="%s" />' % <URL to the image> image_tag.short_description = 'Image' image_tag.allow_tags = True
并在你的admin.py
添加:
fields = ( 'image_tag', ) readonly_fields = ('image_tag',)
到你的ModelAdmin
。 如果要限制编辑图像字段的function,请确保将其添加到exclude
属性。
注意:只有在readonly_fields中,Django 1.8和“image_tag”才会显示。 与'image_tag'只在领域,它给了一个未知领域的错误。 您需要它在字段和readonly_fields为了正确显示。
除了Michael C. O'Connor的回答
请注意,在Django v.1.9
image_tag.allow_tags = True
已被弃用, 您应该使用format_html(),format_html_join()或mark_safe()来代替
因此,如果您将上传的文件存储在公共/目录文件夹中,则代码应如下所示:
Class Model1(models.Model): image = models.ImageField(upload_to=directory) def image_tag(self): return mark_safe('<img src="/directory/%s" width="150" height="150" />' % (self.image)) image_tag.short_description = 'Image'
并在你的admin.py中添加:
fields = ['image_tag'] readonly_fields = ['image_tag']
对于Django 1.9要在编辑页面中显示图像而不是文件path,使用ImageWidget是很好的方法。
from django.contrib.admin.widgets import AdminFileWidget from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe from django.contrib import admin class AdminImageWidget(AdminFileWidget): def render(self, name, value, attrs=None): output = [] if value and getattr(value, "url", None): image_url = value.url file_name = str(value) output.append(u' <a href="%s" target="_blank"><img src="%s" alt="%s" /></a> %s ' % \ (image_url, image_url, file_name, _('Change:'))) output.append(super(AdminFileWidget, self).render(name, value, attrs)) return mark_safe(u''.join(output)) class ImageWidgetAdmin(admin.ModelAdmin): image_fields = [] def formfield_for_dbfield(self, db_field, **kwargs): if db_field.name in self.image_fields: request = kwargs.pop("request", None) kwargs['widget'] = AdminImageWidget return db_field.formfield(**kwargs) return super(ImageWidgetAdmin, self).formfield_for_dbfield(db_field, **kwargs)
用法:
class IndividualBirdAdmin(ImageWidgetAdmin): image_fields = ['thumbNail', 'detailImage']
图像将显示为字段, thumbNail
和detailImage
它可以在pipe理员没有修改模型的情况下完成
from django.utils.html import format_html class Model1Admin(admin.ModelAdmin): def image_tag(self, obj): return format_html('<img src="{}" />'.format(obj.image.url)) image_tag.short_description = 'Image' list_display = ['image_tag',] admin.site.register(Model1, Model1Admin)
使用django-imagekit你可以添加像这样的图像:
from imagekit.admin import AdminThumbnail @register(Fancy) class FancyAdmin(ModelAdmin): list_display = ['name', 'image_display'] image_display = AdminThumbnail(image_field='image') image_display.short_description = 'Image' readonly_fields = ['image_display'] # this is for the change form
虽然这里已经有了一些很好的function性的解决scheme,但是我觉得非forms标记(例如辅助图像标记)属于模板,而不是添加到Django表单小部件中,或者在模型pipe理类中生成。 更多的语义解决scheme是:
pipe理模板覆盖
注意:显然我的声望不够高,不能发布两个以上的简单链接,所以我在下面的文本中创build了注释,并在该答案的底部包含了相应的URL。
从Djangopipe理站点文档 :
重写pipe理模块用于生成pipe理站点各种页面的许多模板相对比较容易。 您甚至可以为特定的应用程序或特定的模型覆盖这些模板中的一部分。
Django的django.contrib.admin.options.ModelAdmin
(通常在命名空间django.contrib.admin.ModelAdmin
下访问)提供了一系列Django模板加载器的模板path,从最具体到最不重要的顺序。 这段代码是直接从django.contrib.admin.options.ModelAdmin.render_change_form
复制的:
return TemplateResponse(request, form_template or [ "admin/%s/%s/change_form.html" % (app_label, opts.model_name), "admin/%s/change_form.html" % app_label, "admin/change_form.html" ], context)
因此,考虑到前面提到的Djangopipe理模板覆盖文档和模板searchpath,假设创build了一个应用程序“articles”,其中定义了一个模型类“Article”。 如果想要覆盖或只扩展model.models.Article的默认Djangopipe理站点更改表单,可以执行以下步骤:
- 为覆盖文件创build一个模板目录结构。
- 虽然文档没有提到它,但是如果
APP_DIRS
1设置为True
,那么模板加载器将首先在app目录中查找。 - 因为我们想通过应用标签和模型来覆盖Djangopipe理站点模板,所得到的目录层次结构是:
<project_root>/articles/templates/admin/articles/article/
- 虽然文档没有提到它,但是如果
- 在一个新的目录结构中创build模板文件。
- 只有pipe理员更改表单需要被覆盖,所以创build
change_form.html
。 - 最后的绝对path是
<project_root>/articles/templates/admin/articles/article/change_form.html
- 只有pipe理员更改表单需要被覆盖,所以创build
- 完全覆盖或简单地扩展默认的pipe理更改表单模板。
- 我无法在Django文档中find关于默认pipe理站点模板可用的上下文数据的任何信息,所以我不得不查看Django源代码。
- 默认更改表单模板:github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
- 一些相关的上下文字典定义可以在
django.contrib.admin.options.ModelAdmin._changeform_view
和django.contrib.admin.options.ModelAdmin.render_change_form
find
- 我无法在Django文档中find关于默认pipe理站点模板可用的上下文数据的任何信息,所以我不得不查看Django源代码。
我的解决scheme
假设模型上的ImageField属性名称是“file”,我的模板覆盖实现图像预览将类似于:
{% extends "admin/change_form.html" %} {% block field_sets %} {% if original %} <div class="aligned form-row"> <div> <label>Preview:</label> <img alt="image preview" src="/{{ original.file.url }}" style="max-height: 300px;"> </div> </div> {% endif %} {% for fieldset in adminform %} {% include "admin/includes/fieldset.html" %} {% endfor %} {% endblock %}
original
似乎是从中生成ModelForm的模型实例。 顺便说一下,我通常不使用内联CSS,但它不值得一个单独的规则的文件。
资料来源:
- docs.djangoproject.com/en/dev/ref/settings/#app-dirs