인스타그램 좋아요 기능을 클론하던 중 ManyToMany 관계를 이용해서 모델링을 하다가 related_name 이 왜 필요한지에 대해 알게 되는 계기가 있었다.
다음은 게시물 모델 Posting 이다.
Posting 모델의 컬럼은
created_time
, content
, user
, liked_users
로 구분이 되어있다.
Posting 모델은 User 모델을 one-to-many 관계로 참조하고 있다.
문제는 여기서 발생했었다.
Posting 과 User 모델을 many-to-many 관계로 이어주기 위해 Posting 모델에서 User 모델을 liked_users
라는 컬럼을 통해 참조했었다. 이 때는 related_name
을 명시해 주지 않은 상태였는데 이대로 makemigration 을 수행하니까 다음과 같은 오류가 났다.
Reverse accessor for 'Posting.user' clashes with reverse accessor for 'Posting.liked_users'
알고보니, 하나의 모델에서(Posting) 여러 컬럼이(user, liked_users) 다른 동일한 모델(User)을 참조할 때 역참조 접근을 위해 쓰는 <User instance>.posting_set
의 이름이 겹쳤기 때문이였다.
User 인스턴스를 만들어서 <User instance>.posting_set
으로 접근해야 한다. User 객체 자체로 하면 안된다.
User 모델에 연결된 Posting 을 user
fk 를 통해 역참조하기 위해 원래는 <User instance>.posting_set
을 통해 접근했다.
하지만 Posting 모델에 User 를 연결한 liked_users
가 추가되면서 User 에서 Posting 을 역참조할 수 있는 방법이 두가지가 생긴 것이다.
user
fk 를 통해liked_users
fk 를 통해Posting 에서 정참조하는 fk 에 related_name 을 설정해주지 않았을 때는 User instance 에서 posting_set
으로 접근하면 되지만
지금은 Posting 필드 두개에서 User 를 참조하고 있기 때문에, User 에서 Posting 을 어떤 fk 를 통해 역참조 해야할지 모른다.
<User instance>.posting_set
은 user fk 을 이용해 참조 한 것이다.
liked_users
필드에 related_name 을 설정해주면,<User instance>.<related_name>
으로 User 에서 Posting 으로 역참조가 가능해진다!
related_name='liked_postings' 으로 가정해보자.
어떤 유저가 자신이 게시한 모든 포스팅을 보고싶다 ?
--> <User instance>.posting_set
어떤 유저가 자신이 좋아요 한 모든 포스팅을 보고싶다 ?
--> <User instance>.liked_postings
fk (외래키) 에 related_name 을 지정할 땐 보통 <자기가 속하는 테이블 명의 복수> 마지막에 적어줘서 어떤 모델이 이 테이블을 역참조 할 때 어떤 테이블을 참조해서 어떤 값을 가져오는지 명확히 하기 위해서다.
user.liked_postings
유저가 좋아요한 포스팅 전부