Published on

Django Admin에서 이미지 미리보기 구현하는 방법

Authors

Django admin에서 이미지 필드(ImageField)의 이미지를 바로 미리보기로 확인할 수 있도록 만드는 간단한 방법 입니다. Inline의 경우 설정이 조금 다른데, 어떤 방식으로 이미지를 보여지게 할 수 있는지 공유합니다.

기본적으로 모델에 ImageField 이 있어야합니다. 다음과 같은 모델이 있다고 가정합니다.

class Product(models.Model):
    name = models.CharField(max_length=100)
    image = models.ImageField(upload_to='products/')

1. Admin에서 미리보기 추가

Django admin에서 HTML을 안전하게 표시하기 위해 주로 format_html을 사용하는 것이 좋습니다. 예전에 스택오버플로우에서 알게되어 mark_safe를 활용하기도 했었는데, mark_safe는 직접 HTML을 삽입하기 때문에 XSS 취약성이 있어 주의가 필요하다고 합니다.

  • format_html은 변수를 자동으로 HTML 이스케이프 처리하여 XSS 위험을 방지합니다. (format_html 이 훨씬 간편하기도 하니, 사용하는 것이 좋은 것 같습니다.)

admin.py에 미리보기 메서드를 추가합니다.

from django.contrib import admin
from django.utils.html import format_html
from .models import Product

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ['name', 'image_preview']

    @admin.display(description="이미지 미리보기")
    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 100px;" />', obj.image.url)
        return "-"

2. Inline 모델에서 이미지 미리보기 추가

기본 admin.ModelAdmin에서 이미지 미리보기를 추가하는 방법외에 실제로 Inline을 통해서 세부페이지를 구현하는 경우가 종종 있습니다. 위의 방식대로 list_display를 사용하면 Inline에서는 이미지 미리보기가 적용되지 않습니다.

InlineAdmin(TabularInline 등)에서는 list_display가 아닌 fields와 readonly_fields를 이용해 이미지 미리보기를 구현 해야합니다.


class ProductImageInline(admin.TabularInline):
    model = Product
    extra = 0
    fields = ['name', 'image', 'image_preview']
    readonly_fields = ['image_preview']

    @admin.display(description="이미지 미리보기")
    def image_preview(self, obj):
        if obj.image:
            return format_html('<img src="{}" style="max-height: 100px;" />', obj.image.url)
        return "-"

3. 이미지가 보이지 않는 경우

settings.py 혹은 MEDIA 설정을 꼭 확인합니다. 스토리지가 잘못설정된 경우도 더러 있을 수 있습니다.

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

# urls.py에서 아래처럼 urlpatterns에 추가되어 있는지 확인합니다.

from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
  • hongreat 블로그의 글을 봐주셔서 감사합니다!^^
  • 내용에 잘못된 부분이나 의문점이 있으시다면 댓글 부탁 & 환영 합니다~!
  • (하단의 버튼을 누르시면 댓글을 보거나 작성할 수 있습니다.)
Buy Me A Coffee