2023/09/15 [TIL] 데이터베이스의 모델 관계 & related_name으로 역참조해서 데이터 가져오기

장현웅·2023년 9월 15일
0

related_name은 일대일 관계나 일대다 관계에서 사용하는 것이 일반적이다.

다대다 관계에서는 하나의 객체가 여러 개의 연결된 객체를 가지고, 연결된 객체 또한 여러 개의 객체와 관련될 수 있기 때문에 related_name을 사용하면 이름 충돌이 발생할 수 있다.

다대다 관계에서 related_name을 사용하려면 모델 설정 시 모델 간 관계를 잘 정의해줘야한다.

🐣 일대일관계 OneToOneField


한 모델의 각 객체 인스턴스가 다른 모델의 하나의 객체 인스턴스랑만 연결된다.

from django.db import models

class Husband(models.Model):
    name = models.CharField(max_length=100)
    marriage_date = models.DateField()
    wife = models.OneToOneField('Wife', related_name='rn_husband', on_delete=models.CASCADE)


class Wife(models.Model):
    name = models.CharField(max_length=100)
    marriage_date = models.DateField()
    husband = models.OneToOneField(Husband, related_name='rn_wife', on_delete=models.CASCADE)

남자와 여자를 나타내는 두 모델은 OneToOneField를 통해 연결되었다.

on_delete=models.CASCADE는 둘 중 한 데이터만 삭제되도 연결된 데이터도 함께 삭제된다.

related_name을 사용해서 남자와 여자가 서로를 역참조해서 서로의 정보를 가져올 수 있다.

그럼 데이터베이스에 데이터가 저장되어 있다고 가정하고, alex라는 남자의 아내 데이터를 가져와보자.

husband_alex = Husband.objects.get(name='Alex', marrige_date = '2023-09-15')
wife_lily = Wife.objects.get(name='Lily', marrige_date = '2023-09-15')

alex_wife = husband_alex.rn_wife
Lily_husband = wife_lily.rn_husband

일대일 관계에서 related_name을 통해 데이터를 가져올 때는 .get()이나 .filter() 함수 없이 역참조를 통해 데이터를 가져올 수 있다.

🐤 일대다 관계 ForeignKey


한 쪽에서는 여러 개의 연결을 가질 수 있지만, 다른 쪽에서는 하나의 연결만 가지는 관계

팀과 팀원으로 일대다 관계 모델을 정의해보자.

from django.db import models

class Team(models.Model):
    name = models.CharField(max_length=100)

class TeamMember(models.Model):
    name = models.CharField(max_length=100)
    role = models.CharField(max_length=100)
    team = models.ForeignKey(Team, related_name='rn_member', on_delete=models.CASCADE)
  

팀과 팀원을 나타내는 두 모델은 ForeignKey를 통해 연결되었다.

on_delete=models.CASCADEForeignKey로 참조된 팀 모델 데이터가 삭제되면 참조한 팀원 모델 데이터도 삭제된다.

related_name을 사용해서 팀과 팀원은 서로를 역참조해서 서로의 정보를 가져올 수 있다.

이번에 팀 프로젝트를 진행했는데, 6조 sixsense 팀 그리고 팀원 데이터가 데이터베이스에 저장되어있다고 생각하고 데이터를 가져오는 것을 해보자.

sixsense_team = Team.objects.get(name='sixsense')
member1_alex = TeamMember.objects.get(name='Alex')


alex = sixsense_team.rn_member.filter(name='Alex')
alex_team = member1_alex.rn_member.filter(name='sixsense') 

.get(조건) 함수는 해당 조건을 만족하는 유일한 객체를 가져오는데

만약, 데이터베이스에 해당 객체가 없으면 오류가 발생하기 때문에 filter(조건) 함수를 사용하는 것이 좋다.

🐥다대다 관계 ManyToManyField


하나의 객체가 다른 여러 객체와 관계를 맺을 수 있는 관계형이다. 모델 필드에 ManyToManyField를 선언하면 중간테이블이 저절로 생긴다. 이 중간테이블은 모델 사이의 관계를 저장하고 관리한다.

from django.db import models

class User(models.Model):
	name = models.CharField(max_length=100)
    
class Post(models.Model):
	username = models.ForeignKey('User', related_name='rn_post', on_delete=models.CASCADE)
	title = models.CharField(max_length=100)
    content = models.CharField(max_length=100)
    like = models.ManyToManyField('self', related_name="rn_like", blank=True)
    bookmark = models.ManyToManyField('self', related_name="rn_bookmark", blank=True)
    

related_name을 통해서 데이터를 가져와보자.

  • Alex 유저
alex = User.objects.get(name='Alex')
  • Alex의 모든 포스트
alex_all_posts = alex.rn_post.all()
  • Alex의 첫 번째 포스트
alex_first_posts = alex.rn_post.first()
  • Alex가 like한 포스트
alex_liked_posts = alex.rn_like.all()
  • Alex가 bookmark한 포스트
alex_bookmarked_posts = alex.rn_bookmark.all()

🥚🐣🐤🐥🐓🐔

0개의 댓글