몰입공간

[Django] related_name 속성으로 역참조 객체 불러오기(getting objects in reverse relation by setting a related_name) 본문

Programming/Django

[Django] related_name 속성으로 역참조 객체 불러오기(getting objects in reverse relation by setting a related_name)

sahayana 2022. 1. 31. 19:21

 


#1.  related_name

 


구현하려는 웹 어플리케이션이 다양한 서비스를 제공한다면, 이에 따른 데이터 관계도 분명 복잡해집니다.

이러한 참조관계에 이름을 부여하여 직관적인 이해를 돕는 장고 모델의 related_name 속성이 있습니다.

related_name은 한 모델에 같은 모델을 2개 이상 참조하는 등의 상황에 따라 필수적으로 부여해야 할 때도 있습니다.

(사실, related_name을 설정하지 않을 때 더욱 직관적인 경우도 있습니다..)

 

여기서는 1:N 관계의 대표격인 게시글-댓글 관계를 통해 참조와 related_name 속성을 알아보려고 합니다.

 

 

Post모델을 미리 설정했다는 가정하에 Comment모델을 생성합니다.

post 속성을 ForeignKey로 설정하고 related_name 속성에 'comments'를 설정합니다.

# models.py
class Comment(models.Model):

    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.TextField()
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)

#2.  정참조와 역참조

 

Comment 모델은 Post모델의 외래키로 받아 정참조하는 관계입니다.

따라서 Comment 모델은 post 속성으로 Post의 객체를 바로 조회할 수 있습니다.

장고 Shell을 통해 comment객체의 post 속성을 통해 post 객체의 모든 속성을 접근할 수 있습니다.

from mysite.models import Post, Comment

comment_1 = Comment.objects.get(id=5)
comment_1.post.title
>>> 'Django 블로그 튜토리얼(5) - Comment 모델 설정'

 

반대로 Post객체는 Comment 객체와 역참조 관계이므로 바로 접근할 수 없습니다.

post_1 = Post.objects.get(id=5)
post1.comment.all()
>>> AttributeError: 'Post' object has no attribute 'comment'

post에 달린 댓글 객체를 확인하려면 모델이름_set 으로 조회가 가능합니다.

post_1 = Post.objects.get(id=5)
post1.comment_set.all()
>>> <QuerySet[<Object Comment Object(1)>, <Object Comment Object(2)>]>

related_name은 set과 똑같은 기능을 합니다.

(템플릿 태그를 사용하는 경우에도 똑같이 작용합니다.)

post_1 = Post.objects.get(id=5)
post1.comments.all()
>>> <QuerySet[<Object Comment Object(1)>, <Object Comment Object(2)>]>

#3. 필수적인 related_name

 

참고로, 동일한 모델을 2개 이상의 속성으로 연결시키는 경우 related_name을 필수적으로 명시하여야 합니다.

명시하지 않을 경우 조회할 쿼리의 기준이 명확하지가 않아 마이그레이션 과정에서 오류가 나게 됩니다. 

 

다음과 같이 댓글에 recommend 필드를 설정하고 user모델을 연결시키는 경우 필수적으로 related_name
지정해야 합니다.

 

# models.py
class Comment(models.Model):

    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    content = models.TextField()
    created_date = models.DateTimeField(auto_now_add=True)
    updated_date = models.DateTimeField(auto_now=True)
    recommend = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name = 'recommends')

 

Comments