[파이썬 장고] Django 의 ContentType Framework - GenericRelation 활용하기 #1 Python

이 글은 장고 v1.10 (현재 시점 최신버전) 을 기준으로 작성된 것입니다.

===============================================================

최근에 장고를 열심히 하고있다... 사실상 장고만 하고있다고 봐야지.. -ㅅ-;; ㅋㅋ
그러니 장고를 계속 요모조모 뜯어볼 수 밖에 없는 현실이다.

최근에 보고있던 것이 바로 장고에서 제공하는 ContentType 프레임웤이라는 것인데...
이것의 활용을 가지고 최근에 삽질을 좀 많이 한 바람에 그냥 내 나름대로 알게된것들을 조금 적어보고자 한다.

공식 도큐먼테이션을 잘 읽어보면 뭐 해석잘하는 분들이야 알아서 잘 하시겠지만 그 글을 읽기도 싫고, 적당히 개념만 쉽게 알고 싶다는 분들은 쭉 한번 읽어보시길 바란다.

===============================================================

일단 Django Content type framework 라는 것은 한마디로 줄인다면 아래와 같다.

"하나의 테이블에서 범용적으로 다른 테이블에 조인(=foreign key)을 걸고싶을때 사용하는 것"

즉 예를 들어, 테이블 A 에서 테이블 B 와 테이블 C 로 동일한 필드를 사용 해 링크(=조인)를 걸고싶다는 것이다.
Django Native Library 에서는 이 기능을 여러종류의 테이블별 사용자의 권한관리를 위해 Authentication Framework 에서 사용하고 있다고 밝히고 있다.

자, 그렇다면 이제부터 장고 코딩을 한번 해보자.
요구사항은 아래와 같다고 가정하자.

블로그 포스팅(Post)과 비디오(Video) 라는 컨텐츠에 태그(Tag) 시스템을 적용하여라

자, 그럼 순서대로 진행해보자.

1. Content Type 프레임워크 설치

프로젝트 세팅 파일의 INSTALLED_APPS 에 아래를 추가하자
'django.contrib.contenttypes'

모델의 실 Dataabase 적용을 위해 아래 명령어를 프로젝트 홈폴더에서 실행
$> python manage.py migrate

그럼 DB 에 django_content_type 이라는 테이블이 생긴것을 알 수 있을것이다.

2. 모델 제작 하기

모델 선언을 해보자
일단 포스트 와 비디오 테이블은 아래와 같을것이다.

========== models.py ==========
from django.db import models

class Post(models.Model):
# Post related data fields
...

class Video(models.Models):
# Video related data fields
...
==============================

그럼 나는 일단 태그를 저장하기 위한 테이블을 아래와 같이 만들것이다.

========== models.py 이어서... ==========
class Tag(models.Models):
# Video related data fields
...
=============================

그런데 Tag 에서 Post 와 Video 테이블 둘다에 범용적인 필드를 생성하여 Foreign Key 를 두고싶다.
태그 테이블(Tag) 에서 블로그 포스트(Post) 와 비디오(Video) 두 가지 종류의 모델에 범용적인 관계(Generic Relation)를 생성하고 싶은 것이다. 그에따라 각 모델은 아래와 같이 변경된다.

========== models.py ==========

from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericRelation

class Post(models.Model):
# Post related data fields
...
tags = GenericRelation(Tag, object_id_field='object_id', content_type_field='content_type', related_query_name='posts')

class Video(models.Models):
# Video related data fields
...
tags = GenericRelation(Tag, object_id_field='object_id', content_type_field='content_type', related_query_name='videos')

class Tag(models.Models):
# Video related data fields
...
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, db_column='content_type_id')
object_id = modelsPositiveIntegerField(db_column='object_id')
content_object = GenericForeignKey('content_type', 'object_id')

=============================

그럼 코드 하나하나 설명 들어간다.
일단 Tag - Post, Tag - Video 는 둘다 many-to-many 관계임을 염두해 두자

- Tag 쪽에서 content_type 이라는 필드를 두었는데 이것은 django_content_type 테이블에서 지정된 특정 테이블을 지칭한다.
  해당 모델 타입의 객체를 얻고 싶으면 django_content_type.id 와 매칭되는 Tag 테이블의 content_type_id 를 유의 하면 됨.

- content_type 은 연결 모델의 객체타입을, object_id 는 해당 모델타입의 Primary Key  필드와 연결된다. 반드시 Primary Key 이어야 한다.

- GenericRelation 은 컨텐츠 모델이 ContentType 프레임웍을 통해 어떤 모델과 연관성이 있다는 것을 알기 위해 정의 되어있는 것이다.

 GenericRelation 의 object_id_field 는 범용테이블(Tag) 의 object_id, content_type_field 는 범용테이블의  content_type 필드를 의미하는 것이다. 만약에 Tag 의 해당용도 필드명이 item_type 과 item_id 였다면
object_id_field='item_id', content_type_field='item_type'
로 바뀌었을 것이다.

.
.
.
아직 더 이야기할게 많이 남긴 했는데... 
※ 추가적인 내용은 업데이트 또는 후속 편을 통해 이야기할 예정 !!!




통계 위젯 (블랙)

5945
703
304557

GoogleAdsenseResponsive

Cluster map