Django

django | 정참조, 역참조 유저 profile, hobby

JOOHUUN 2022. 6. 18. 16:00
# 유저 모델
class User(AbstractBaseUser):
    username = models.CharField("사용자 계정", max_length=50, unique=True)
    password = models.CharField("비밀번호", max_length=128)
    email = models.EmailField("이메일 주소", max_length=100)
    fullname = models.CharField("이름", max_length=20)
    join_date = models.DateField("가입일", auto_now_add=True)

    is_active = models.BooleanField(default=True)

    is_admin = models.BooleanField(default=False)


# 취미 모델
class Hobby(models.Model):
    name = models.CharField("취미 이름", max_length=20)
    def __str__(self):
        return self.name
        
        
# 프로필 모델       
class Profile(models.Model):
    # user = models.ForeignKey(User, verbose_name="유저", on_delete=models.CASCADE, unique=True)
    user = models.OneToOneField(User, verbose_name="유저", on_delete=models.CASCADE)
    introduction = models.TextField("자기소개", null=True, blank=True)
    birthday = models.DateField("생일", null=True, blank=True)
    age = models.IntegerField("나이")
    hobby = models.ManyToManyField(Hobby, verbose_name="취미")

    def __str__(self):
        return f"{self.user.username} 님의 프로필입니다."

 

1. 외래키(ForeignKey) 종류

  • ForeignKey : many-to-one 형태로 특정 테이블에서 다른 테이블을 참조 할 수 있다. 
  • OneToOneField : FoerignKey와 동일 하지만, 1대1 관계만 가능하다.  사용자는 한걔의 프로필만 가질수 있다. 
  • ManyToManyField : 프로필은 여러개의 취미를 가질 수 있고, 취미또한 여러 사용자가 겹칠 수 있다.

2. 역참조

외래 키를 사용해 참조하는 object를 역으로 찾을 수 있다.

프로필 모델의 쿼리에는 hobby = models.ManyToManyFiled로 취미 모델을 참조하고 있다. 

여기서 related_name을 지정해주면 related_name를 사용하여 불러 올 수있음

related_name은 지정하지 않았을 겨우 set_을 사용하여 불러 올 수 있음(필수값아님) 

## related_name 지정한 경우
# user/models.py
hobby = models.ManyToManyField(Hobby, verbose_name="취미", related_name="hobby")
# user/views.py 
hobby_members = hobby.hobby.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True)

## related_name 지정하지 않은 경우
# user/models.py
hobby = models.ManyToManyField(Hobby, verbose_name="취미")
# user/views.py 
hobby_members = hobby.profile_set.exclude(user=user).annotate(username=F('user__username')).values_list('username', flat=True)

 

 

ex) OneToOneFileds만 예외로 set_을 사용하지 않고 불러 올수 있음

ex) 역참조를 사용하여 1번프로필의 취미 불러오기,

취미와 프로필의 관계

- 프로필이 취미를 참조하고있다.

- 취미는 프로필을 역참조 하고 있다.