Django/Django Rest Framework
12. Django DRF 외래 키
S.T.Lee
2022. 6. 19. 10:39
외래 키 종류
- ForeignKey : many-to-one 형태로 특정 테이블에서 다른 테이블을 참조 할 수 있다,
- 영화관과 시청자의 관계를 나타 낼 때, 시청자 테이블에서 영화관 테이블을 Foreign Key를 사용해 관계를 맺을 수 있다.
- OneToOneField : one-to-one 형태로 ForeignKey와 동일하지만, 1:1 관계만 가능하다.
- 사용자 계정 테이블과 사용자 프로필 테이블이 별도로 존재 할 때, 계정 테이블을 프로필에서 1:1로 관계를 맺을 수 있다.
- ForeginKey(unique=True)로 설정해주는거랑 같다.
- ManyToManyField : many-to-many 형태로 한 개의 필드에서 여러개의 테이블을 참조 할 수 있다.
- 영화라는 테이블에서 카테고리 테이블의 object를 참조하고 싶을 때, many to many 관계를 사용해 2개 이상의 object를 참조할 수 있다.
- Many-to-many 관계로 생성 된 필드는 db에 값이 2개 이상 저장되는 것이 아닌, 중간 테이블이 생성된다.
모델 필드에 따른 DB 저장 방식
from ntpath import join
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
# Create your models here.
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
if not username:
raise ValueError('Users must have an username')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password=None):
user = self.create_user(
username=username,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
username = models.CharField("사용자 계정", max_length=50, unique=True)
password = models.CharField("비밀번호", max_length=200)
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)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = []
objects = UserManager()
def __str__(self):
return f"{self.username} / {self.email} / {self.fullname}"
#권한 설정 #손 건들일이 없다
def has_perm(self, perm, obj=None):
return True
#손 건들일이 없다
def has_module_perms(self, app_label):
return True
@property
def is_staff(self):
return self.is_admin
class UserProfile(models.Model):
user = models.OneToOneField(to=User, verbose_name="사용자", on_delete=models.CASCADE, primary_key=True)
hobby = models.ManyToManyField("Hobby", verbose_name="취미")
introduction = models.TextField("소개")
birthday = models.DateField("생일")
age = models.IntegerField("나이")
def __str__(self):
return f"{self.user.username} 님의 프로필"
class Hobby(models.Model):
name = models.CharField("취미", max_length=50)
def __str__(self):
return self.name
분명 UserProfile에 hobby를 만들었는데 hobby가 없는것을 볼 수 있다. 그 이유는 외래 키에 2개 이상의 id값이 들어갈 수 없어서 DB자체적으로 중간 테이블을 만들기 때문이다. 위에서 userprofile_hobby라는 만들지 않은 테이블이 생성된것을 볼 수 있다.
상단과 같이 userprofile과 hobby가 값으로 있는 중간 테이블 구조를 볼 수 있다.