web-dev-qa-db-ja.com

Django Imagefieldからの管理者表示画像

List_displayでアップロードした画像を表示できますが、モデルごとのページでこれを行うことは可能ですか(モデルを変更するために取得するページのように)?

簡単なサンプルモデルは次のとおりです。

Class Model1(models.Model):
    image = models.ImageField(upload_to=directory)

デフォルトの管理者は、アップロードされた画像のURLを表示しますが、画像自体は表示しません。

ありがとう!

52
Jeff_Hd

確かに。モデルクラスに次のようなメソッドを追加します。

def image_tag(self):
    from Django.utils.html import escape
    return u'<img src="%s" />' % escape(<URL to the image>)
image_tag.short_description = 'Image'
image_tag.allow_tags = True

そしてあなたのadmin.py追加:

fields = ( 'image_tag', )
readonly_fields = ('image_tag',)

ModelAdminに。画像フィールドの編集機能を制限する場合は、exclude属性に追加してください。

注:Django 1.8および 'image_tag'はreadonly_fieldsのみで表示されませんでした。'image_tag 'がフィールドのみであると、不明なフィールドのエラーが発生しました。フィールドと正しく表示するためにreadonly_fields。

106

マイケル・C・オコナーの答えに加えて

In Django v.1.9

image_tag.allow_tags = True

廃止され、 代わりにformat_html()、format_html_join()、またはmark_safe()を使用する必要があります

アップロードしたファイルをpublic/directoryフォルダーに保存する場合、コードは次のようになります。

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']
52
palamunder

モデルを変更せずに管理者で実行できます

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

For Django 1.9編集ページでファイルパスの代わりに画像を表示するには、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フィールドの画像が表示されます

16
Venkat Kotra

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
9
Risadinha

ここですでに共有されているいくつかの優れた機能的なソリューションがありますが、補助画像タグなどの非フォームマークアップはテンプレートに属し、Django=フォームウィジェットまたはモデルで生成された管理クラス:より意味的な解決策は次のとおりです。

管理テンプレートのオーバーライド

注:どうやら私の評判は2つ以上の単純なリンクを投稿するほど高くないので、次のテキストで注釈を作成し、それぞれのURLを含めましたこの答えの下部にあります。

Django Admin Site documentation から:

管理モジュールが管理サイトのさまざまなページを生成するために使用するテンプレートの多くをオーバーライドするのは比較的簡単です。特定のアプリまたは特定のモデル用にこれらのテンプレートのいくつかをオーバーライドすることもできます。

DjangoのDjango.contrib.admin.options.ModelAdmin(ネームスペースDjango.contrib.admin.ModelAdminで一般にアクセス)は、 Djangoのテンプレートローダー への一連の可能なテンプレートパスを提示します。このスニペットは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)

したがって、前述のDjango adminテンプレートオーバーライドドキュメントとテンプレート検索パスを考慮して、モデルクラス "Article"が定義されているアプリ "articles"を作成したと仮定します。または拡張onlyデフォルトのDjangoモデルarticles.models.Articleの管理サイト変更フォーム]の場合、次の手順を実行します。

  1. オーバーライドファイルのテンプレートディレクトリ構造を作成します。
    • ドキュメントには記載されていませんが、テンプレートローダーは、APP_DIRS1 Trueに設定されます。
    • Django管理サイトテンプレートをアプリラベルおよびモデルごとにオーバーライドする必要があるため、結果のディレクトリ階層は<project_root>/articles/templates/admin/articles/article/になります。
  2. テンプレートファイルを新しいディレクトリ構造に作成します。
    • オーバーライドする必要があるのは管理者変更フォームだけなので、change_form.htmlを作成します。
    • 最終的な絶対パスは<project_root>/articles/templates/admin/articles/article/change_form.htmlになります
  3. デフォルトの管理者変更フォームテンプレートを完全にオーバーライドするか、単に拡張します。
    • Djangoデフォルトの管理サイトテンプレートで利用可能なコンテキストデータに関するドキュメントで情報を見つけることができなかったため、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にあります。

私のソリューション

モデルのImageField属性名が「ファイル」であると仮定すると、イメージプレビューを実装するためのテンプレートのオーバーライドは次のようになります。

{% 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を使用しませんが、単一のルール用に別のファイルを用意する価値はありませんでした。

ソース:

  1. docs.djangoproject.com/en/dev/ref/settings/#app-dirs
7
monotonee

これは Django 2.1を変更せずにmodels.py

Heroモデルには、画像フィールドがあります。

headshot = models.ImageField(null=True, blank=True, upload_to="hero_headshots/")

次のようにできます:

@admin.register(Hero)
class HeroAdmin(admin.ModelAdmin, ExportCsvMixin):

    readonly_fields = [..., "headshot_image"]

    def headshot_image(self, obj):
        return mark_safe('<img src="{url}" width="{width}" height={height} />'.format(
            url = obj.headshot.url,
            width=obj.headshot.width,
            height=obj.headshot.height,
            )
    )
3
Alex Jolig

Venkat Kotraの answer のDjango 2.1アップデート。答えはDjango 2.0.7以下で問題なく動作します。ただし、サーバー500エラー(DEBUG=Falseの場合)または

render() got an unexpected keyword argument 'renderer'

その理由は、Django 2.1:Support for Widget.render() methods without the renderer argument is removed.であるため、param rendererは現在必須です。AdminImageWidgetの関数render()を更新して、param rendererを含める必要があります。 attrsの後(必要な場合はkwargsの前):

class AdminImageWidget(AdminFileWidget):
    def render(self, name, value, attrs=None, renderer=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, renderer))
        return mark_safe(u''.join(output))
1
John Pang