본문으로 건너뛰기
Advertisement

Django Admin 커스터마이징

Django Admin은 모델 기반으로 자동 생성되는 관리자 인터페이스입니다. 추가 코드 없이 CRUD 기능을 즉시 사용할 수 있습니다.


기본 Admin 등록

# products/admin.py
from django.contrib import admin
from .models import Category, Product, Review


# 기본 등록
admin.site.register(Category)

# 데코레이터 방식
@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
pass

list_display — 목록 컬럼

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# 목록에 표시할 필드
list_display = ["id", "name", "price", "stock", "category", "is_active", "created_at"]

# 링크 필드
list_display_links = ["id", "name"]

# 목록에서 바로 수정
list_editable = ["is_active", "stock"]

# 필터 사이드바
list_filter = ["is_active", "category", "created_at"]

# 검색
search_fields = ["name", "description", "owner__email"]

# 정렬
ordering = ["-created_at"]

# 페이지당 항목 수
list_per_page = 25

# 계산 필드 (메서드로 추가)
def price_display(self, obj):
return f"{obj.price:,}원"
price_display.short_description = "가격"
price_display.admin_order_field = "price" # 정렬 허용

상세 편집 폼 커스터마이징

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
# 상세 폼 필드 그룹
fieldsets = [
("기본 정보", {
"fields": ["name", "description", "category"],
}),
("가격 및 재고", {
"fields": ["price", "stock"],
"classes": ["wide"],
}),
("설정", {
"fields": ["is_active", "owner"],
"classes": ["collapse"], # 접기
}),
]

# 읽기 전용 필드
readonly_fields = ["created_at", "updated_at"]

# 자동완성 (외래키 필드)
autocomplete_fields = ["category", "owner"]

# 원시 ID 필드 (성능)
raw_id_fields = ["owner"]

# 수평 필터 (ManyToMany)
# filter_horizontal = ["tags"]

커스텀 액션

from django.contrib import admin, messages


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "is_active", "stock"]
actions = ["activate_products", "deactivate_products", "restock"]

@admin.action(description="선택 상품 활성화")
def activate_products(self, request, queryset):
count = queryset.update(is_active=True)
self.message_user(request, f"{count}개 상품이 활성화되었습니다")

@admin.action(description="선택 상품 비활성화")
def deactivate_products(self, request, queryset):
count = queryset.update(is_active=False)
self.message_user(
request,
f"{count}개 상품이 비활성화되었습니다",
messages.WARNING,
)

@admin.action(description="재고 100개로 초기화")
def restock(self, request, queryset):
from django.db.models import F
count = queryset.update(stock=100)
self.message_user(request, f"{count}개 상품 재고가 100개로 설정되었습니다")

Inline — 관련 모델 동시 편집

from django.contrib import admin
from .models import Product, Review


class ReviewInline(admin.TabularInline): # 또는 StackedInline
model = Review
fields = ["author", "rating", "comment"]
readonly_fields = ["created_at"]
extra = 0 # 기본 빈 폼 수
max_num = 10


@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
list_display = ["name", "price", "review_count"]
inlines = [ReviewInline]

def review_count(self, obj):
return obj.reviews.count()
review_count.short_description = "리뷰 수"

def get_queryset(self, request):
# 쿼리 최적화
return super().get_queryset(request).prefetch_related("reviews")

권한 제어

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
return request.user.is_superuser

def has_change_permission(self, request, obj=None):
if obj and obj.owner == request.user:
return True
return request.user.is_staff

def has_delete_permission(self, request, obj=None):
return request.user.is_superuser

def get_queryset(self, request):
"""일반 관리자는 자신의 상품만 볼 수 있음"""
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)

Admin 사이트 커스터마이징

# myproject/admin.py
from django.contrib import admin

# 사이트 기본 정보 변경
admin.site.site_header = "My Shop 관리자"
admin.site.site_title = "My Shop Admin"
admin.site.index_title = "대시보드"

정리

기능속성/메서드
목록 컬럼list_display
직접 수정list_editable
사이드바 필터list_filter
검색search_fields
폼 그룹fieldsets
읽기 전용readonly_fields
커스텀 액션actions + @admin.action
관련 모델 인라인TabularInline / StackedInline
권한 제어has_*_permission()

Django Admin은 내부 도구나 콘텐츠 관리 시스템으로 가장 적합합니다.

Advertisement