Django Admin-4 : 템플릿 커스텀하기

Ho Kim·2022년 11월 2일
0

기존 템플릿을 커스텀 하는 방법에 대해서는 Django Admin-1에서 다루었다.

오늘 [템플릿 커스텀하기]에서는 동일한 내용을 조금 더 심화적으로 살펴볼 것이다.

1. 기본 세팅

1) django 기본 템플릿 찾기

django 어드민에 사용되는 템플릿은 모두 django모듈 내부에 contrib/admin/templates/admin 폴더 내부에 있다.

저 위치를 매번 찾아가는 것은 너무 귀찮은 방법인데 vscode사용자라면 폴더를 열지 않아도 내용을 살펴볼 수 있다.

먼저 admin.py에 들어간다.
장고에서 제공하는 기본 어드민을 사용하기 위해 django.contrib에서 admin을 가져왔을 것이다.

표시된 항목을 Ctrl + 클릭 (mac인 경우 Cmd + 클릭)하면 django.contrib.__init__.py로 이동된다.

여기에서 상단 주소 표시줄을 누르면 원하는 위치로 이동이 가능하다. 이곳에서 contrib/admin/templates/admin로 들어가 변경하고 싶은 템플릿을 찾으면 된다.

2) settings.py 되짚기

첫번째 글에서 템플릿 수정을 하기 위해 'DIRS': [BASE_DIR / 'templates'] 을 추가했다.
django가 템플릿을 확인할 추가 위치를 지정한 것이다.

...

TEMPLATES = [
   {
       'BACKEND': 'django.template.backends.django.DjangoTemplates',
       'DIRS': [BASE_DIR / 'templates'],
             'APP_DIRS': True,
             'OPTIONS': {
                 'context_processors': [
                     'django.template.context_processors.debug',
                     'django.template.context_processors.request',
                     'django.contrib.auth.context_processors.auth',
                     'django.contrib.messages.context_processors.messages',
                 ],
             },
         },
     ]

위에서 변경하고 싶은 기존 템플릿을 찾았다면, 이제 프로젝트의 루트에 templates/admin 폴더를 만들고 동일한 이름으로 내용을 복붙한 뒤에 파일을 수정하면 된다.

2. change list에 버튼 추가하기

1) 파일 가져오기


change list 에 표시한 위치에 버튼을 추가하고 싶다. change list는 change_list.html에서 가져오는데, change_list.html의 내용을 살펴보니 수정하고자 하는 부분은 다른 html에서 수정되는 듯 하다.
1.1)과 같은 방법으로 objct_tools.html을 찾는다.

파일을 열고 내용을 복사한 뒤에 동일한 이름으로 templates/admin 위치에 파일을 만든다.

제대로 연결되었는지 확인해 보기 위해
'Add'라는 단어를 '추가'로 바꿔보자.

{% load i18n admin_urls %}

{% block object-tools-items %}
{% if has_add_permission %}
<li>
	{% url cl.opts|admin_urlname:'add' as add_url %}
	<a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
    
		<!-- 수정된 부분 시작 -->
		{% blocktranslate with cl.opts.verbose_name as name %}{{ name }} 추가{% endblocktranslate %}
		<!-- 수정된 부분 끝 -->
	</a>
</li>
{% endif %}
{% endblock %}


성공적으로 변경되었다!

2. 버튼 정보 넘기기

버튼을 html에서 보여주려면 버튼에 대한 정보를 넘겨야한다. html을 변경하기 전에 html에서 렌더링할 정보를 넘겨주는 부분을 먼저 작성하자.

admin.ModelAdmin에서 changelist_view를 오버라이딩할 것이다.
changelist_view는 인자로 extra_context를 받는데, 이 extra_context는 context와 합쳐져 changelist와 연결된 html에 전달된다.

class UserAdmin(admin.ModelAdmin):
    list_display = ('id', 'user_name', 'recent_login','isRecentlyLogined2')
    fields =  ('id', 
               ('user_img_url', 'imgThumbnail'),
               'user_name','user_pass', 
               ('recent_login','isRecentlyLogined2'))
    readonly_fields =  ('isRecentlyLogined2', 'imgThumbnail')

	...

    def changelist_view(self, request, extra_context=None):
        if(extra_context is None):
            extra_context = {}
        extra_context.update({'buttons':[
            {'name':'네이버', 'url':'https://www.naver.com/'},
            {'name':'구글','url':'https://www.google.com/'},
        ]})
        return super().changelist_view(request, extra_context)
     

코드를 보면

  • changelist_view에서 extra_context가 없으면 새로 만들고
  • 버튼과 관련된 내용을 업데이트한 뒤에
  • 부모의 changelist_view에 넘겨주었다.

이렇게 하면 이 정보가 changelist와 연결된 html에 전달된다.


3. 버튼을 넣을 수 있도록 html 변경하기

Django는 html을 렌더링 할때 Django template 문법을 통한 편의를 제공한다.

{{변수명}} 을 통해 context로 제공한 변수에 접근할 수 있고, {% for elem in 변수명%}{% endfor %} 로 for문을 쓸 수도, {% for 변수명%}{% enfif %}로 if문을 쓸 수도 있다.

자세한것은 공식 홈페이지의 설명을 참고하자.

이번에 쓸 것은 for문이다.

1)에서 가져온 change_list_object_tools.html을 연다.

{% load i18n admin_urls %}

{% block object-tools-items %}
{% if has_add_permission %}
<li>
	{% url cl.opts|admin_urlname:'add' as add_url %}
	<a href="{% add_preserved_filters add_url is_popup to_field %}" class="addlink">
		{% blocktranslate with cl.opts.verbose_name as name %}{{ name }} 추가{% endblocktranslate %}
	</a>
    <!-- 추가된 부분 시작 -->
	{% if buttons %}
		{% for btn in buttons %}
		<a href="{{btn.url}}" class="addlink">
			{{btn.name}}
		</a>
		{% endfor %}
	{% endif %}
    <!-- 추가된 부분 끝 -->
</li>
{% endif %}
{% endblock %}

추가된 부분을 보면

  • {% if buttons %} :먼저 buttons 라는 변수가 있는지 확인한다.
  • {% for btn in buttons %} : buttons가 있으면 for문을 통해 내부의 항목을 순회한다.
  • <a href="{{btn.url}}" class="addlink"> {{btn.name}} </a> : 각 항목에 대해 href와 content를 채운 a태그를 반환한다.

저장한 뒤에 새로고침 해보면 정상적으로 버튼이 적용된 화면을 볼 수 있다.

링크도 정상적으로 작동한다.

+)버튼 css 수정

버튼이 딱 달라 붙어 있는 게 마음에 들지 않는다면 Django Admin-3에서 작성한 css파일에 값을 추가해주면 된다.

/* static\css\custom.css */
...

.object-tools a.addlink{
    margin-left: 5px;
}

최종 결과물은 다음과 같다.

버튼이 마음에 들게 추가되었다!

3. change form에 버튼 추가하기

이번에는 change form을 수정해보자.

2번 항목의 반복이라 어렵지 않을 것이다.

1) 파일 가져오기


change_form.html을 보면 원하는 부분이 submit_row와 비슷한 이름을 가진 html에 들어있는 듯 하다.

파일 목록을 살펴보니 submit_line.html이 있다.

내용을 보니 맞게 찾아온 것 같다.

파일을 templates/admin로 복사해온다.
테스트로 각 항목을 한글화 해보자.

{% load i18n admin_urls %}
<div class="submit-row">
{% block submit-row %}
{% if show_save %}<input type="submit" value="저장" class="default" name="_save">{% endif %}
{% if show_delete_link and original %}
    {% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
    <p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">삭제</a></p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% translate 'Save as new' %}" name="_saveasnew">{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="저장 후 새 항목 추가" name="_addanother">{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% if can_change %}저장 후 계속 수정{% else %}{% translate 'Save and view' %}{% endif %}" name="_continue">{% endif %}
{% if show_close %}<a href="{% url opts|admin_urlname:'changelist' %}" class="closelink">{% translate 'Close' %}</a>{% endif %}
{% endblock %}
</div>

결과는 다음과 같다.

성공적으로 한글화되었다!

2) 버튼 정보 넘기기

이번에는 changeform_view를 오버라이딩 해야한다.
changeform에서는 이동이 아니라 기능 버튼을 만들어 볼 것이다.
클릭시 알럿창, 콘솔창에 메세지를 띄우는 js 코드를 넣어보자.

class UserAdmin(admin.ModelAdmin):
    list_display = ('id', 'user_name', 'recent_login','isRecentlyLogined2')
    fields =  ('id', 
               ('user_img_url', 'imgThumbnail'),
               'user_name','user_pass', 
               ('recent_login','isRecentlyLogined2'))
    readonly_fields =  ('isRecentlyLogined2', 'imgThumbnail')

	...
    
    def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
        if(extra_context is None):
            extra_context = {}
        extra_context.update({'buttons':[
            {'name':'알럿 메세지', 'script':'alert("Hello")'},
            {'name':'콘솔 메세지', 'script':'console.log("World")'},
        ]})
        return super().changeform_view(request, object_id, form_url, extra_context)

3. html 변경하기

html에 for문으로 버튼을 추가한다.

{% load i18n admin_urls %}
<div class="submit-row">
{% block submit-row %}
{% if show_save %}<input type="submit" value="저장" class="default" name="_save">{% endif %}
{% if show_delete_link and original %}
    {% url opts|admin_urlname:'delete' original.pk|admin_urlquote as delete_url %}
    <p class="deletelink-box"><a href="{% add_preserved_filters delete_url %}" class="deletelink">삭제</a></p>
{% endif %}
{% if show_save_as_new %}<input type="submit" value="{% translate 'Save as new' %}" name="_saveasnew">{% endif %}
{% if show_save_and_add_another %}<input type="submit" value="저장 후 새 항목 추가" name="_addanother">{% endif %}
{% if show_save_and_continue %}<input type="submit" value="{% if can_change %}저장 후 계속 수정{% else %}{% translate 'Save and view' %}{% endif %}" name="_continue">{% endif %}
{% if show_close %}<a href="{% url opts|admin_urlname:'changelist' %}" class="closelink">{% translate 'Close' %}</a>{% endif %}
{% endblock %}

<!-- 추가된 부분 시작 -->
{% if buttons %}
	{% for btn in buttons %}
		<button type="button" onclick="{{btn.script}}">
			{{btn.name}}
		</button>
	{% endfor %}
{% endif %}
<!-- 추가된 부분 끝 -->

</div>

change_list에서 한것과 거의 동일하다.
change_list에서는 a태그에 href를 넣어주었다면 이번에는 button 태그에 onclick script를 넣어주었다는 것이 다르다.

저장 후 실행시켜보자.


스크립트 실행에 성공했다!

이제 원하는 대로 템플릿을 커스텀할 수 있을것이다.


상세 코드는 다음을 참고:

https://github.com/hokim2407/django-admin_study/tree/56028dd6c6ad3497e955862eaf9d2560ec57e615

0개의 댓글