Published on

Django Admin 커스텀 버튼 추가하기

Authors

Django Admin은 기본 제공 기능만으로는 원하는 작업을 수행하기 어려울 수 있습니다.

버튼자체를 추가하는 것은 html, JS로 어떻게든 할 수 있지만, Django Admin에서 제공하는 기능(?)들을 활용하여 액션을 수행할 수 있는 버튼을 만드는 것이 바람직하다고 생각합니다.

Django Admin에서 커스텀 버튼을 추가하는 두 가지 방법 기록 합니다.

첫 번째 방법은 리스트에 버튼을 추가하는 것이고, 두 번째 방법은 템플릿을 상속받아서 상단에 버튼을 추가하는 것입니다.

1. 리스트에 버튼 추가하기

리스트 뷰에 버튼을 추가하면 row 별로 버튼(액션)을 추가할 수 있고, 저는 각 객체마다 개별적인 액션을 수행하는 UI가 필요하다고 판단되면 이 방법을 사용합니다.

특정 객체의 IP 주소를 가져오는 버튼을 추가할 수 있습니다.

먼저, 모델 어드민 클래스에 버튼을 추가하는 메서드를 정의합니다.


from django.contrib import admin
from django.urls import path
from django.utils.html import format_html
from django.http import HttpResponseRedirect

@admin.register(TempModel)
class TempModelAdmin(admin.ModelAdmin):
    list_display = ["id", "some_field"]

    @admin.display(
        description="버튼",
    )
    def some_method(self, obj):
        button = format_html(
            "<button class ='custom-button' onclick=\"location.href='{}'\">버튼 누르기</button>",
            "/admin/app_name/temp_model/{}/some-method/".format(obj.id),
        )

        return button

    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path(
                "<path:object_id>/some-method/",
                self.admin_site.admin_view(self.get_some_data),
                name="get_some_data",
            ),
        ]
        return custom_urls + urls

    def get_some_data(self, request, object_id):
		    """
		    동작 생략
		    """

        return HttpResponseRedirect(f"/admin/app_name/temp_model/{object_id}")

  • get_urls: 커스텀 URL 패턴을 정의합니다. <path:object_id>/some-method/ 패턴을 추가하여 get_some_data 메서드와 연결합니다.
  • get_some_data: 커스텀 뷰 함수로, 버튼 클릭 시 실행될 작업을 정의합니다. 내부 로직은 생략했습니다.

2. 상단에 버튼 추가하기

상단에 버튼을 추가하면 리스트 뷰 상단에 공통 액션 버튼을 배치할 수 있습니다.

로직이 특정 객체에 귀속되어 있는 것이 아니고, 다양한 객체를 추가한다거나 특정 페이지로 이동해야하는 UX 를 유도하려면 이 방법이 제일 괜찮은 것 같습니다.

2.1 버튼 추가를 위한 템플릿 수정

먼저, change_list.html 템플릿을 수정합니다.

change_list 는 Django Admin 의 기본 템플릿으로 list_display 되는 화면의 템플릿입니다.

프로젝트의 템플릿 디렉토리에 아래 내용을 포함하는 템플릿 파일을 생성합니다. app_name/templates/chage_list.html

{% extends "admin/change_list.html" %}
{% block object-tools-items %}
    {{ block.super }}
    <li>
        <a href="{% url 'admin:get_ip' %}" class="button">IP 확인 및 가져오기</a>
    </li>
{% endblock %}

2.2 모델 어드민 클래스 수정

다음으로, 모델 어드민 클래스에서 커스텀 URL을 추가하고, 해당 URL과 연결된 뷰를 정의합니다.

from django.contrib import admin
from django.urls import path
from django.shortcuts import redirect
from django.contrib import messages

@admin.register(TempModel)
class TempModelAdmin(admin.ModelAdmin):
    list_display = ["id", "some_field"]
    change_list_template = "change_list.html"

    def get_urls(self):
        urls = [
            path("some_method/", self.wrap(self.get_some_method), name="some_method"),
        ]
        return urls + super().get_urls()

    def wrap(self, view):
        def wrapper(*args, **kwargs):
            return self.admin_site.admin_view(view)(*args, **kwargs)
        return update_wrapper(wrapper, view)

    def get_some_method(self, request):
		    """
		    로직 생략
		    """
        return redirect("admin:app_ip_changelist")

get_urls 함수는 Django Admin에서 커스텀 URL 패턴을 정의하고, 특정 작업을 수행하기 위해 매우 중요한 역할을 합니다.

이를 통해 기본 CRUD 작업 외에도 다양한 커스텀 작업을 관리자 인터페이스에 통합할 수 있습니다.

hongreat 블로그의 글을 봐주셔서 감사합니다!