[Django] Model - One To One
One To One
-
1 : 1
관계 -
ForeignKey 에
unique=True
옵션을 준 것과 의미상 동일 -
중복값이 없기 때문에(
unique=True
) Primary Key 로 지정가능 -
역방향 참조를 할 경우
related_name
의 기본값이
classname_set
이 아닌classname
이 된다. -
참조의 반환값(역방향 참조 포함)이 단일 인스턴스이다. (QuerySet 이 아니다.)
Example
예시로 임의의 온라인게임과 유저가 있고,
유저에게는 단 한개의 캐릭터만 생성이 가능하다.
캐릭터는 다음과 같은 데이터를 가지고 있다.
-
유저네임 (username)
-
레벨 (level)
-
직업 (selected_class)
-
유저의 private data (private_data) (
OneToOneField
)
유저의 private data 는 다른 테이블에서 따로 관리하고자 한다.
Django Model Code
from django.db import models
class Character(models.Model):
username = models.CharField(max_length=20)
level = models.IntegerField()
selected_class = models.CharField(max_length=10)
private_data = models.OneToOneField(
'PrivateData',
on_delete=models.CASCADE
)
def __str__(self):
return self.username
class PrivateData(models.Model):
name = models.CharField(max_length=20)
phone_number = models.CharField(max_length=30)
address = models.CharField(max_length=100)
def __str__(self):
return self.name
Practice
위의 구현된 모델을 통해 실제 인스턴스(객체)를 생성하고 확인해보자.
실습을 위해 oto 라는 이름을 가진 app 을 생성하고 해당 앱의 models.py 에 구현코드를 작성한다.
이후makemigrations
와migrate
를 하였음을 가정한다.
# Alice 와 Bruce 의 Private Data 생성
alice = PrivateData.objects.create(name='Alice', phone_number='000-0000', address='A city')
bruce = PrivateData.objects.create(name='Bruce', phone_number='111-1111', address='B city')
# 유저 aaa (Alice) 와 유저 bbb (Bruce) 를 생성
aaa = Character.objects.create(username='aaa', level=30, selected_class='Wizard', private_data=alice)
bbb = Character.objects.create(username='bbb', level=50, selected_class='Warrior', private_data=bruce)
aaa.private_data
>>> <PrivateData: Alice>
bbb.private_data
>>> <PrivateData: Bruce>
alice.character # 역방향 참조
>>> <Character: aaa>
bruce.character # 역방향 참조
>>> <Character: bbb>
Notice
One To One 관계인 만큼 이미 관계를 가진 데이터는 다른 데이터에서 연결할 수 없다.
ccc = Character.objects.create(username='ccc', level=999, selected_class='Warrior', private_data=bruce)
>>> IntegrityError: UNIQUE constraint failed: oto_character.private_data_id
ccc 의 private_data 의 대상을 bruce 로 지정하였다.
하지만 bruce 는 이미 bbb 의 private_data 로 지정되어 있기 때문에
위와 같은 에러가 발생함을 알 수 있다.
DataBase
Table List
-
oto_character
-
oto_privatedata
oto_character
id | username | level | selected_class | private_data_id |
---|---|---|---|---|
1 | aaa | 30 | Wizard | 1 |
2 | bbb | 50 | Warrior | 2 |
oto_privatedata
id | name | phone_number | address |
---|---|---|---|
1 | Alice | 000-0000 | A city |
2 | Bruce | 111-1111 | B city |
Leave a comment