무효 클릭 IP 추적 중...
파이썬/django(장고)

[django 기초] Foreign Key(외래키)관계에서의 reverse_name 사용법

꼬예 2021. 7. 30.

Foreign Key관계에 있는 Post 모델과 Comment 모델을 만들어 보았습니다. 

 

Post 한개에 여러개의 Comment 가 올 수 있지만 Comment 한개에 여러개의 Post가 올수 없기 때문에

 

Post : Comment = 1 : N 관계라고 할 수 있는데요.. 

 

아래와 같이 N 위치에 있는 모델에 ForeignKey를 지정을 해줍니다. 

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    message = models.TextField()
    photo = models.ImageField(blank=True)
    is_public = models.BooleanField(default= False, verbose_name='공개여부')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)


class Comment(models.Model):
    post = models.ForeignKey(Post, on_delete=models.CASCADE) 
    message = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

코드를 보시면 ForeignKey 메소드 첫번째 인자에 내가 연결할 모델을 넣어주고, on_delete 인자에 models.CASCADE를 넣어 줍니다.  models.CASCADE가 의미하는것은 만약 연결된 Post 객체가 삭제가 될 경우 Comment도 같이 삭제하겠다라는 의미입니다.  

 

models.CASCADE 외에도 다양한 방법이 있으니 , 공식문서를 참조해주시기 바랍니다. 

 

실제로 post 라는 필드는  우리 눈앞에 나타나는 필드가 아닌 내부적인 필드라고 할 수 있는데요.

필드명_id 라는 이름으로 데이터베이스에 저장이 되고 채워지는 값은 연결된 상위 객체(여기선 post객체)의 id를 가져와 채워 넣습니다. 

 

실제로 그런지 확인해볼까요?

우선 Comment 모델을 makemigrations 할때 생긴 파일의 이름을 확인하고,

 

python manage.py sqlmigrate blogapp 0002

해당 명령어를 통해 sql query를 확인해보겠습니다.(참고로 blogapp 은 해당 모델이 속해있는 앱 명입니다..)

우리가 집중해서 봐야할 부분은 파란 사각형입니다. 

post_id 라는 명으로 값이 만들어졌고 blogapp의 post 모델을 references한다는 것을 알 수 있죠.

 

 

이제 우리가 알고싶은것은 Comment 객체를 가지고 현재 이 Comment 객체가 가리키고 있는 Post 객체를 어떻게 알 수 있는지에 대한 문제 입니다. 

 

Comment객체를 기준으로 Post객체 찾기

개념설명에 앞서 제가 임의로 모델 객체들을 생성하고 연결지어 보았는데요.

 Post 모델 객체는 총 4개  , Comment  모델 객체는 총 3개 그리고 서로 간의 관계는 그림과 같습니다.  

 

다시말하면  Post:object 3에 Comment:object 3 이 딸려있고, Post:object 4 에 Comment:object1 , Comment:object2 가 딸려 있다는 말입니다. 

만약 Post:object 4를 지우면 한번에 Comment:object1 , Comment:object2 두개가 삭제되겠죠?

 

 

이제 본론으로 들어가보죠!

python manage.py shell

shell을 실행하고, 우리가 만든 모델을 import 하겠습니다.

from blogapp.models import Comment, Post


먼저 해볼것은 Comment 객체를 기준으로 해당 객체가 Post 의 몇번 객체랑 연결되어있는지 알아보겠습니다. 

위 그림에서처럼 comment:object 3을 한번 불러오고, 이 친구가 연결되어있는 post객체가 누구인지 알아보겠습니다. 

 

우선 comment_3이라는 변수명으로 object 3을 불러오죠.

comment_3 = Comment.objects.get(pk=3)

 

앞서 Comment 모델을 생성할때 자동적으로 post_id 라는 필드에 연결되어있는 상위 객체 id값이 들어가 있다고 한것 기억나시나요? 

post_id 로 불러온 3이라는 값은 이 객체가 연결되어 있는 post 객체의 id 값입니다. 

즉 아래와 같은 방법으로 Pos t객체를 찾아 낼수가 있습니다.

 

위 방법 외에도 아래와 같이 더 심플하게 값을 불러 올 수 있는데요.

이때 주의 할것은  해당 필드 명대로 적어줘야 불러진다는 것입니다. 

만약,  post_1 로 저장을 했다면,

아래와 같이 적어줘야 불러진다는거 참고하시기 바랍니다. 

 

Post객체를 기준으로 Comment객체찾기

지금까지는 comment객체를 기준으로 연결되어 있는 post객체를 찾았다면 이번엔 역으로 찾아보도록 하겠습니다. 

 

이번에 관심이 있는건 post 4 객체에 딸려 있는 comment들은 어떤것이 있는 가입니다.

 

먼저 아래와 같이 객체를 생성합니다. 

post_4 = Post.objects.get(pk=4)

그 후 해당 객체를 이용해 아래와 같이 값을 찾아줍니다.

 

앞서 comment 객체 기준으로 Post 객체를 찾는것과 다르게 get 이 아닌 filter를 사용했습니다. 왜냐하면 post에 딸린 객체는 여러개일 가능성이 있기 때문이죠.

 

이 방법외에도 post 필드명에 바로 해당 객체를 넣어도 아래와 같이 똑같은 결과를 얻을 수 있습니다. 

 

그렇다면 귀찮게 filter 사용하지 않고 더 편한 방법은 없을까요?

 

앞서 했던 방법대로 하게되면  아래와 같이 오류가 맞이하게됩니다...

 

왜냐하면 Comment 모델에선 post라는 필드명이 있었지만 , Post 모델에서는 Comment에 연결 당하고(?) 있다라는  표시를 나타내는 필드가 없기 때문이죠. 그럼 어떻게 할까요?

 

바로 모델명의소문자_set의 형태로 접근 해주면 우리가 원하는 결과를 얻을 수 있습니다. 

 

 

 

이 글과 읽으면 좋은글

  • 트위터 공유하기
  • 페이스북 공유하기
  • 카카오톡 공유하기
이 컨텐츠가 마음에 드셨다면 커피 한잔(후원) ☕

댓글