django_ManyToManyField

강현구·2021년 12월 15일
0

Django

목록 보기
2/12

Many To Many 관계 (다대다)

두개의 테이블의 서로 간에 한개 이상의 Row를 참조하고 있는 관계이다.
많이 사용하는 예시 중에 피자와 토핑이 있는데, '피자'라는 테이블과 '토핑'이라는 테이블이 있다면, 각각의 레이블들은 다른쪽의 여러개의 레이블들을 가질 수 있다.

Many To Many Field

Model 설계 시에 한쪽의 table model에 ManyToManyField를 선언해준다.
어느 쪽에 해도 기능상으로는 크게 차이가 없지만 일반적으로는 main 테이블에 넣어준다.
대신, 둘다 넣으면 table의 순서만 바꾼 다른 테이블이 중복으로 생기게된다.

class Topping(models.Model):
    name     = models.CharField(max_length=20)
    
class Pizza(models.Model):
    name     = models.CharField(max_length=20)
    toppings = models.ManyToManyField('Topping')

ManyToManyField는 기본적으로 관계된 두 테이블 사이의 중간 테이블을 자동으로 생성해준다. 이 중간 테이블에서 FK로 각각의 테이블을 참조하는 형태가 만들어진다.

  1. ForeignKey 선언에서 사용했던 on_delete는 필수 요소가 아니다.
    : on_delete는 참조하는 1쪽의 데이터가 사라졌을 때, 어떻게 데이터를 처리할 것인지에 대한 설정이다.

    • CASCADE : 이와 연결되어 있는 모든 N 쪽 데이터를 삭제.
    • PROTECT : 1인 쪽의 데이터가 삭제가 되지 않도록 보호.
    • SET_NULL : null 로 값을 대체하게 되어 필드에 null=True 옵션이 있어야만 가능.
    • SET_DEFAULT : default 로 값을 대체하게 되며, 필드에 default=True 옵션이 있어야만 가능.
    • SET : 대체할 값이나 함수를 지정.
    • DO_NOTHING : 아무 것도 하지 않지만 db 에서 오류가 발생할 수 있음.
  2. 정참조, 역참조

# N -> 1
comment.post

# 1 -> N
post.comment_set

N인 쪽에서는 관계되어 있는 모델이 하나이므로 바로 접근이 가능하지만, 1인 쪽에서는 관계되어 있는 객체가 많기 때문에 set 을 통해서 접근할 수 있다.
역참조는 (소문자로된 테이블명)\_set의 형태로 사용할 수 있다.

  1. through

ManyToManyField가 기본적으로 중간 테이블을 생성해주지만, through를 통해 중간 테이블을 이름에 맞춰 생성할 수 있다.

왜 사용하는가?

ManyToManyField 를 사용하지 않더라도 직접 중간 테이블을 만들고 그 관계로 DB를 만들 수도 있다.
다시말해, 기능을 동일하게 구현하는 작업은 가능은 하다.
(FK로 중간테이블에서 엮어준다.)
하지만 이렇게 묶어주게 되면 연결되어 있는 다른쪽의 테이블과 연관된 작업을 할경우 중간테이블을 거쳐서 넘어가야한다.
코드가 효율적이지 못하게 된다.
또한 코드가 길고 가독성 또한 떨어지게 되어 관계를 파악하고, 유지보수 하는데에 불편함이 생길 수 밖에 없다.
따라서 ManyToManyField로 엮어 한쪽에서 Foreign Key로 바로 다른 테이블을 보고 있는 것처럼 만들어준다.
이렇게하면, 정참조, 역참조를 통해 쌍방으로 데이터를 참조해갈 수 있다.

참고
jiffydev.log
ambitiouskyle.log

profile
한걸음씩

0개의 댓글