모델 상속

» Django, Model

게시판을 카테고리별로 구분하여 관리를 용이하게 하기 위해 모델 상속을 구현했다.

구조

게시판을 카테고리별로 나누어 각각 Community, QnA, Notice로 구분하며, 이들은 통합적으로 관리하는 Forum이 있다.
기본 모델인 Post는 author, title, body, tag, created라는 필드를 가지고 있다. board/models.py L8-13

각 카테고리별로 모델을 생성할 때는 Post 모델을 상속받는다. L27-37
이렇게 생성된 카테고리 모델들은 추가적인 필드 없이 구현되어, 기본적으로 스켈레톤(뼈대) 구현만을 한다.
이러한 방식의 상속을 통해, 각 모델은 마커 클래스의 역할을 하게 된다.

마커 클래스는 추가적인 구현 없이 타입 체크나 분류를 위해 사용되는 클래스이다.

상속을 통해, 데이터베이스 마이그레이션 시 각 카테고리 모델의 테이블은 기본 Post 테이블을 참조하는 구조로 생성된다.
상속받은 모델에서 쿼리를 실행하면, 해당 모델에 맞게 베이스 모델 Post에서 데이터를 가져오되, 현재 모델의 범위로 제한된다. views.py L18
따라서 모든 레코드는 기본 Post 테이블에서 중앙집중적으로 관리되며 상황에 따라 범위를 다르게 하여 데이터 처리를 할 수 있다.

아래 데이터베이스 테이블이 보인다.

post

notice community qna

첫 번째 테이블인 Post 테이블이 중앙집중적 관리를 보여주며, 다음 세 개의 테이블은 기본키+외래키로 참조하고 있다.
각 테이블은 독립적이며 합하면 Post 테이블임을 알 수 있다.

ERD, Joined Table Inheritance

아래의 ERD는 Board 앱의 모델 상속 구조를 추상화하여 보여준다.
ERD

이 구조에서는 관계형 데이터베이스의 상속 관계를 표현하기 위해 Joined Table Inheritance 전략을 적용하였다.
이 전략에서 기본 테이블은 슈퍼타입으로, 상속받은 테이블은 서브타입으로 모델링된다.
각 서브타입 테이블은 슈퍼타입 테이블의 기본 키를 상속받아 기본 키이자 외래 키로 사용한다. 레코드들이 겹치지 않고 독립적이므로, 각각의 서브타입 테이블은 슈퍼타입 테이블과 1:1 관계를 가진다.

구현

urls.py 파일에서는 urlpatterns_of 함수를 사용하여 하위 경로들을 그룹화하고, 각 카테고리별로 다른 뷰를 연결해 주었다.
이를 통해 app_name (include의 두 번째 인자)과 namespace를 활용하여 템플릿에서도 네임스페이스를 구분할 수 있다.

views.py 파일에서는 뷰들을 묶어 클래스화했으며, 각 인스턴스는 내부 변수로 해당 카테고리의 모델을 가지게 된다.
뷰 클래스는 구현이 같으며 인스턴스를 통해 구분된다. views.py L10-12

View 함수 안에선 request.resolver_match.namespace를 사용하여 정의된 네임스페이스를 알 수 있다.
하지만, 구현을 줄이기 위해 각 인스턴스 생성시에 모델 외에도 네임스페이스를 내부 변수로 저장하여 필요할 때 사용하게 되었다. L13

ModelForm은 instance 인수로 현재 컨텍스트의 모델 인스턴스를 전달받아, 모델 타입에 맞게 모델폼의 타입을 구체화한다. L51
이 접근 방식으로 인해 모델폼에서 별도의 마커 클래스가 필요하지 않는다.

템플릿에서는 {app_name}:{path_name} 형태로 URL 네임스페이스를 사용할 수 있으며, 하드 코딩을 줄이기 위해 current_url이라는 커스텀 태그를 만들었다. templatetags/url_utils.py L6-10
이 태그는 Django 템플릿 라이브러리에 simple_tag 데코레이터를 사용하여 등록되며, HTML 생성 시에 해당 태그가 해석된다. ../templates/board/board.html L39