Django Admin에서 html template를 커스텀해 JS를 사용하는 방법을 알아보려고 한다.
간단한 ERD와 요구사항은 다음과 같다.
요구사항
- Django admin에서 Data 생성 시, 외래키로 2개의 데이터를 설정해야 한다.
- B 외래키를 설정함에 있어서 A외래키의 영향을 받아 동적으로 변경되어 보여져야 한다.
시도한 방법
- Django.jquery를 사용하는 방법
- 경로설정과 세팅에 대한 공수가 커 비효율적이다.
- admin inner template 활용
- django admin 에서 add, change 등의 상황마다 template이 내장되어있다.
- Admin Class 내에서 커스텀 하기 용이한 함수도 있기에 효율적이라고 판단했다.
해결 방법
1. Admin 클래스에서 필요한 데이터 로드 및 변환
Introduction 모델의 Admin 클래스에 change_form_template 를 커스텀해야한다.
(기본적으로 admin 의 페이지는 모든 내장 템플릿으로 동작 하기 때문에, 템플릿을 오버라이딩 하여 커스텀이 가능하다.)
여기서 directory는 app/templates/{name}/{something.html} 인 경우 {name}/{something.html} 로 지정한다.
from django.contrib import admin
from .models import Introduction, Career, Company
import json
class IntroductionAdmin(admin.ModelAdmin):
change_form_template = 'introduction/change_form.html'
def render_change_form(self, request, context, *args, **kwargs):
companies = Company.objects.all()
careers = {
company.id: [
{'id': career.id, 'name': career.name} for career in Career.objects.filter(company=company)
] for company in companies
}
careers_json = json.dumps(careers)
context['companies'] = companies
context['careers_json'] = careers_json
return super().render_change_form(request, context, *args, **kwargs)
admin.site.register(Introduction, IntroductionAdmin)
2. 템플릿에서 JavaScript 로직 작성
커스터마이징 할 템플릿에 동적 업데이트 필드를 구현하기 위해 JS를 이용한다.
사용하여 company 필드의 변경을 감지하고, 관련된 career 목록을 동적으로 업데이트합니다.
{% extends "admin/change_form.html" %}
{% block extrahead %}
{{ block.super }}
<script>
document.addEventListener('DOMContentLoaded', function() {
const companyField = document.getElementById('id_company');
const careerField = document.getElementById('id_career');
const careersData = JSON.parse('{{ careers_json|escapejs }}');
if (companyField && careerField) {
companyField.addEventListener('change', function() {
const companyId = parseInt(this.value);
const careers = careersData[companyId] || [];
careerField.innerHTML = '';
careers.forEach(career => {
const option = document.createElement('option');
option.value = career.id;
option.text = career.name;
careerField.appendChild(option);
});
});
}
});
</script>
{% endblock %}
- {% extends "admin/change_form.html" %} 로 Django 어드민의 기본 change_form.html 템플릿을 확장한다.
- {% block extrahead %} 블록은 <head> 섹션에 추가적인 내용을 삽입할 수 있게 해주며 여기에 JavaScript 를 작성하면된다
- DOMContentLoaded 이벤트 리스너: document.addEventListener('DOMContentLoaded', function() {...});는 HTML 문서가 완전히 로드된 후에 코드를 실행하도록 하게해준다.
- companyField와 careerField는 각각 회사와 직무의 <select> 엘리먼트를 참조하는데, getElementById를 사용하여 해당 엘리먼트를 선택한다.
- const careersData = JSON.parse('{{ careers_json|escapejs }}');는 서버에서 전달한 JSON 형태의 직무 데이터를 JavaScript 객체로 가져온다.
- companyField.addEventListener('change', function() {...});는 회사 선택 필드의 값이 변경될 때마다 실행될 함수를 정의한다.
결론
이 방법을 통해 Django Admin에서 동적인 구현이 필요하다면 템플릿 커스텀이 제일 간단하다. Django 에서 실행되는 기능이과 별도의 호출없이 이용할 수 있다.
'IT CHANNEL > Python' 카테고리의 다른 글
[Django] webp ,바이트 스트림(Byte Stream) 개념과 이미지 webp 형식으로 변환하기 (0) | 2023.09.01 |
---|---|
[Django] data 순서 필드(row number)를 위한 ORM(Window expression),admin에서 cached queryset 구현 (0) | 2023.08.20 |
데이터베이스 샤딩 : Django[DRF]로 Shard_DB에 create, read 구현하기 (0) | 2023.05.14 |
[DRF 게시판만들기] #4 GenericAPIView & Urls (0) | 2022.03.29 |
[DRF 게시판만들기] #3 Serializer, ModelSerializer 개념 및 역할 (0) | 2022.03.20 |