반응형
본 글은 Holix의 "리액트와 함께 장고 시작하기 Complete" 강의를 듣고 작성한 일지입니다.
이번에는 ManyToManyField에 대해 알아보려고 합니다. ManyToManyField는 M:N 관계에서 어느 쪽이라도 필드 지정이 가능합니다. 따라서 아래와 같은 2가지 방법이 있는데요.
방법 1)
class Post(models.Model):
tag_set = models.ManyToManyField('Tag', blank=True)
class Article(models.Model):
tag_set = models.ManyToManyField('Tag', blank=True)
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
방법 2)
class Post(models.Model):
...
class Article(models.Model):
...
class Tag(models.Model):
name = models.CharField(max_length=100, unique=True)
post_set = models.ManyToManyField('Post', blank=True)
article_set = models.ManyToManyField('Article', blank=True)
Tag를 활용한다는 관점에서 보면 아무래도 방법 1이 방법 2보다 더 적절할 것 같습니다. 하지만 이는 개인의 선택이며 M:N 어느 관계에도 필드 지정이 가능하니 좀 더 끌리는 곳을 선택하면 되겠습니다.
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
content = models.TextField()
photo = models.ImageField(blank=True, upload_to=uuid_name_upload_to) # blank=True: 옵션 필드(디폴트는 False)
# 파이썬 클래스는 순서대로 진행, Tag를 참조하는데 Post 클래스 이전에 해당 클래스가 없기 때문에 문법 오류로 표시
# 이때는 문자열로 대체 가능
tag_set = models.ManyToManyField('Tag', blank=True) # tag는 없어도 되므로 blank=True, 그렇지 않으면 장고 form 유효성 검사 통과 X
...
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
python manage.py makemigrations blog1
python manage.py migrate blog1
ManyToManyField를 적용하면 이전의 ForeignKey, OneToOneField와 달리 테이블이 하나 더 생성됩니다. Post와 Tag 클래스를 OneToOneField로 관계를 맺었기 때문에 아래와 같은 이름으로 생성되는데, 이는 장고에서 자동으로 설정하는 중간 테이블입니다.
post = Post.objects.last()
post.tag_set.all() # reverse name이기도 하지만 여기선 필드 이름으로 지정
tag = Tag.objects.first()
tag.post_set.all() # reverse name 활용
Tag.objects.create(name='django')
Tag.objects.create(name='AI')
tag = Tag.objects.get(name='django')
post.tag_set.add(tag)
post.tag_set.remove(tag)
하나씩 태그를 추가하려면 위 방법을 사용하면 되는데, 전체 테크를 다 추가하기 위해선 아래 방법을 사용하면 됩니다.
tag_qs = Tag.objects.all()
post.tag_set.add(*tag_qs) # 파이썬의 unpack 문법: 하나의 인자에 들어있는 것을 여러 개에 풀어주는 방법
post.tag_set.all()
# 파이썬 unpack 문법
def myfn(a, b, c):
print(f'a={}, b={b}, c={c}')
myfn(1, 2, 3) # a=1, b=2, c=3
params = [1, 2, 3]
myfn(*params) # a=1, b=2, c=3
참고
장고는 기본적으로 RDBMS를 지원하지만 DB에 따라 NoSQL 기능도 지원합니다. 하나의 Post 안에 다수의 댓글을 저장할 수 있는 것이 간단한 예시인데요. 아래 라이브러리 정보를 참고하여 json 타입의 데이터가 필요하다면 충분히 사용해볼 수 있겠습니다.
djkoch/jsonfield
- 대개의 DB엔진에서 사용 가능
- TextField/CharField를 래핑
- dict 등의 타입에 대한 저장을 직렬화(serialize)하여 문자열로 저장
하지만 내부 필드에 대해 쿼리 불가
django.contrib.postgres.fields.JSONField
- 내부적으로 PostgreSQL의 jsonb 타입(json binary)
- 내부 필드에 대해 쿼리 지원
adamchainz/django-mysql
- MySQL 5.7 이상에서 json 필드 지원
728x90
반응형
'문돌이 존버 > Django 스터디' 카테고리의 다른 글
장고(Django), 다양한 응답의 함수 기반 뷰(1) (0) | 2021.09.12 |
---|---|
장고(Django), 마이그레이션을 통한 데이터베이스 스키마 관리(1), (2) (0) | 2021.08.15 |
장고(Django), 관계를 표현하는 모델 필드(OneToOneField) (0) | 2021.08.14 |
장고(Django) 관계(relationship)를 표현하는 모델 필드, ForeignKey (0) | 2021.08.07 |
장고(Django) debug toolbar 설치 및 SQL 쿼리문 확인 (0) | 2021.08.07 |