Django Web Framework/Django 일반

django admin에서 list의 항목, 상세 페이지의 항목 커스터마이징 하는 방법

bluebamus 2024. 9. 6.

1. django의 admin을 수정하는 방법은 2가지가 있다. 

   - 정의된 admin class에서 오버라이딩을 통한 방법

   - django에서 제공하는 template를 수정하는 방법

 

2. 이 포스트에서는 admin에서 오버라이딩을 이용하여 수정하는 방법을 정리한다.

   - 문제 정의

      - 썸머노트를 admin의 form에 적용하는 경우, text에 스타일을 정의하면 관련한 html 태그가 저장된다.

         - 나의 경우 title이라는 필드에 저장했으며, list에 출력, 상세 페이지에도 subscript에 출력이 되었다.

      - 생성 후, 리스트에서 확인시, title에 html 태그가 같이 출력이 되고, 상세 페이지에서 subscript에도 동일하게 html 태그가 출력 되었다.

 

   - 해결을 위한 접근 방법

      - chatgpt의 여러 종류를 통해 다양한 질문을 던져봤지만, 정확한 정답을 알려주는 결과는 없었다.

      - 직접 만든 코드를 입력하고, list에서 title의 html 태그를 삭제하는 방법을 질문하는 경우 관련한 코드를 생성해 주었다. 

      - format_html, strip_tags 두 방법에 대해 제시해 줬으며 format_html 방법을 차용했다.

      - 해당 방법은 기존 함수의 오버라이딩이 아닌, 공식 문서에서 제시하는 field 값의 커스텀 방법이다.

      - 문제는 이 방법으로 상세 페이지의 field 정보는 해결할 수 없다.

 

   - 상세 페이지의 subscript의 커스텀을 위한 접근 방법

      - 상속받은 클래스들을 따라가며 title이 어디에서 정의되는지 확인하기로 한다.

# 최초 정의 코드
class WorkExperienceAdmin(AdminCacheClean, SummernoteModelAdmin):

->

# SummernoteModelAdmin 추적 => django_summernote/admin.py
class SummernoteModelAdmin(SummernoteModelAdminMixin, admin.ModelAdmin):
    pass
    
->

# admin.ModelAdmin 추적 => admin/options.py
class ModelAdmin(BaseModelAdmin):

   ...

# 확인된 코드
    @csrf_protect_m
        def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
            with transaction.atomic(using=router.db_for_write(self.model)):
                return self._changeform_view(request, object_id, form_url, extra_context)

        def _changeform_view(self, request, object_id, form_url, extra_context):
            to_field = request.POST.get(TO_FIELD_VAR, request.GET.get(TO_FIELD_VAR))
            if to_field and not self.to_field_allowed(request, to_field):
                raise DisallowedModelAdminToField(
                    "The field %s cannot be referenced." % to_field
                )
            
            ...
            
            context = {
            **self.admin_site.each_context(request),
            "title": title % self.opts.verbose_name,

 

      - 결론적으로 changeform_view 함수를 오버라이딩 하면 된다고 판단했다.

      - 빠른 작업을 위해 관련한 changeform_view 및 _changeform_view 코드를 복사해 chatgpt에 원하는 결과를 입력했다.

 

   - 해결된 코드 결과

      - 기존 title 필드는 get_cleaned_title로 변경되고 관련된 함수가 하단에 정의되었다. 해당 코드는 list에서 출력되는 결과에 대해 html 태그를 제거된 text만 출력하게 만들어 준다.

      - changeform_view 함수에서 먼저 super를 이용해 기존 처리를 완료한 결과를 받도록 만들고 반환된 결과에서 subscript만 format_html()로 html 태그를 제거했다.

class WorkExperienceAdmin(AdminCacheClean, SummernoteModelAdmin):
    cache_prefix = "portfolio"
    use_pk = False

    list_display = [
        "id",
        "get_cleaned_title",
        "role",
        "color",
        "sort_num",
        "language",
        "project_start_date",
    ]
    list_display_links = ["id", "get_cleaned_title", "role"]
    list_editable = (
        "color",
        "sort_num",
        "language",
    )
    summernote_fields = (
        "title",
        "summary",
        "content",
    )

    actions = [
        "delete_all_cache",
        "delete_selected_items",
    ]

    def get_actions(self, request):
        actions = super(WorkExperienceAdmin, self).get_actions(request)
        del actions["delete_selected"]
        return actions

    def get_cleaned_title(self, obj):
        # HTML 태그를 제거하고 텍스트만 반환
        return format_html(
            obj.title
        )  # 또는 obj.title.strip()으로 HTML 제거 가능, 만약 HTML 태그를 제거하고 싶다면, strip_tags를 사용

    get_cleaned_title.short_description = "Title"  # Admin에서 표시될 제목

    def changeform_view(self, request, object_id=None, form_url="", extra_context=None):
        response = super().changeform_view(request, object_id, form_url, extra_context)

        # title에서 HTML 태그를 제거
        if "title" in response.context_data:
            response.context_data["subtitle"] = format_html(
                response.context_data["subtitle"]
            )

        return response

 

3. 완료

   - chatgpt를 사용하면서 느끼는 것이지만, 일반적인 서술적 질문과 간단한 코드 몇줄로는 기본적인 문제의 해결 외에는 원하는 답을 얻기 힘들다.

   - 최대한 문제의 본질에 대한 질문을 하고, 최대한 reference를 제공해야 결과가 쓸만하다.

   - 이런 과정에도 거짓말을 하며 동작하지 않는 코드 혹은 말도 안되는 코드를 제공하는 경우가 많은 편이다.

   - 최대한 기존 admin의 html 파일을 수정하지 않는 방법을 선호하기에 이번 과정에 대해 만족스러웠다.

   - 관련한 정보를 찾을 수 없었다. 물론 해외 커뮤니티를 한참 뒤지다 보면 방법을 찾을 수 있겠지만, 소비될 엄청난 시간대비 정말 짧은 시간에 원하는 결과를 도출했다.

   - 누군가에게 이 글이 도움이 되길 바란다.

 

댓글