programing

Django 관리자 이미지 필드에서 이미지 표시

goodcopy 2021. 1. 16. 10:36
반응형

Django 관리자 이미지 필드에서 이미지 표시


업로드 된 이미지를 list_display에 표시 할 수 있지만 모델 별 페이지에서이 작업을 수행 할 수 있습니까 (모델 변경을위한 페이지에서와 같이)?

빠른 샘플 모델은 다음과 같습니다.

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

기본 관리자는 업로드 된 이미지의 URL을 표시하지만 이미지 자체는 표시하지 않습니다.

감사!


확실한. 모델 클래스에서 다음과 같은 메소드를 추가하십시오.

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 모두에 필요합니다.


Michael C. O'Connor의 답변 외에도

Django v.1.9에서

image_tag.allow_tags = True

더 이상 사용되지 않으며 대신 format_html (), format_html_join () 또는 mark_safe ()를 사용해야합니다.

따라서 업로드 된 파일을 공용 / 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']

모델을 수정하지 않고 관리자에서 할 수 있습니다.

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


함께 장고 - 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

이미 여기에 공유 된 좋은 기능적 솔루션이 있지만 보조 이미지 태그와 같은 비 형식 마크 업은 템플릿에 속하고 Django 양식 위젯에 고정되거나 모델 관리자 클래스에서 생성되지 않는다고 생각합니다. 더 의미 론적 솔루션은 다음과 같습니다.

관리 템플릿 재정의

참고 : 분명히 내 평판은 두 개 이상의 간단한 링크를 게시하기에 충분하지 않으므로 다음 텍스트에 주석을 만들고이 답변의 하단에 각 URL을 포함했습니다.

로부터 장고 관리 사이트 문서 :

관리 모듈이 관리 사이트의 다양한 페이지를 생성하는 데 사용하는 많은 템플릿을 재정의하는 것은 비교적 쉽습니다. 특정 앱 또는 특정 모델에 대해 이러한 템플릿 중 일부를 재정의 할 수도 있습니다.

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)

Therefore, considering the aforementioned Django admin template override documentation and the template search paths, suppose one has created an app "articles" in which is defined a model class "Article". If one wants to override or extend only the default Django admin site change form for model articles.models.Article, one would execute the following steps:

  1. Create a template directory structure for the override file.
    • Although the documentation does not mention it, the template loader will look in app directories first if APP_DIRS1 is set to True.
    • Because one wants to override the Django admin site template by app label and by model, the resulting directory hierarchy would be: <project_root>/articles/templates/admin/articles/article/
  2. Create the template file(s) in one's new directory structure.
    • Only the admin change form needs to be overridden so create change_form.html.
    • The final, absolute path will be <project_root>/articles/templates/admin/articles/article/change_form.html
  3. Completely override or simply extend the default admin change form template.
    • I wasn't able to locate any information in the Django documentation concerning the context data available to the default admin site templates so I was forced to look at the Django source code.
      • Default change form template: github.com/django/django/blob/master/django/contrib/admin/templates/admin/change_form.html
      • A few of the relevant context dictionary definitions can be found in django.contrib.admin.options.ModelAdmin._changeform_view and django.contrib.admin.options.ModelAdmin.render_change_form

My Solution

Assuming that my ImageField attribute name on the model is "file", my template override to implement image previews would be similar to this:

{% 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 appears to be the model instance from which the ModelForm was generated. As an aside, I usually don't use inline CSS but it wasn't worth a separate file for a single rule.

Sources:

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

This is how it worked for django 2.1 without modifying models.py:

In your Hero model, you have an image field.:

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

You can do it like this:

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

Django 2.1 update for Venkat Kotra's answer. The answer works fine on Django 2.0.7 and below. But gives server 500 error (if DEBUG=False) or gives

render() got an unexpected keyword argument 'renderer'

The reason is that in Django 2.1: Support for Widget.render() methods without the renderer argument is removed. So, param renderer is mandatory now. We must update function render() of AdminImageWidget to include param renderer. And it must be after attrs (before kwargs if you have it):

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

ReferenceURL : https://stackoverflow.com/questions/16307307/django-admin-show-image-from-imagefield

반응형