๐ ForeignKey & ManyToManyField
๐ฅ ForeignKey
๐ฅ ManyToManyField
๐ฅ Sting ํํ๋ก ํ
์ด๋ธ ์ฐ๊ฒฐ
1. ForeignKey
- ForeignKey๋ ํ ํ
์ด๋ธ์ ํ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ค๋ฅธ ๋ชจ๋ธ์ ํ
์ด๋ธ์ ์ฐ๊ฒฐ์ํค๋ ๊ธฐ๋ฅ์ผ๋ก ForeignKey๊ฐ ํฌํจ๋ ํ
์ด๋ธ์ '์์ ํ
์ด๋ธ'์ด๊ณ , ForeignKey๋ฅผ ํตํด ์ฐธ์กฐํ ํ
์ด๋ธ์ '๋ถ๋ชจ ํ
์ด๋ธ'์ด๋ผ ํด์.
- ForeignKey๋ '์์ ํ
์ด๋ธ'์ ํ๋ ๊ฐ์ด '๋ถ๋ชจ ํ
์ด๋ธ'์ Primary Key๋ฅผ ์ฐธ์กฐํจ์ผ๋ก์จ ์ผ๋๋ค ๊ด๊ณ๋ก(many-to-one) ํ
์ด๋ธ์ ์ฐ๊ฒฐํ๋๋ฐ, '๋ถ๋ชจ ํ
์ด๋ธ'์ ํ object๊ฐ ์์ ์ ์ฐธ์กฐํ๋ '์์ ํ
์ด๋ธ'์ ์ฌ๋ฌ object์ ์ฐ๋๋์ด DB๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ด์.
1) ForeignKey ๋?
- ์๋ ์ฝ๋๋ฅผ ๋ณด๋ฉด, ์ฌ๋ฌ๊ฐ์ ๊ฐ์ค ์ ๋ณด๋ฅผ ์ ์ฅํ๋ Room ํ
์ด๋ธ์ 'host' ํ๋๊ฐ User ํ
์ด๋ธ์ Primary Key๋ฅผ ์ฐธ์กฐ ํจ์ผ๋ก์จ Room ํ
์ด๋ธ์ object๋ค์ด ์ด๋ค ์ฌ์ฉ์์ ์ฐ๊ฒฐ ์ง์์ง ๊ฒฐ์ ํฉ๋๋ค.
- ForeignKey ์ฌ์ฉ ๋ฐฉ๋ฒ
- ๐ ํ๋๋ช
= ForeignKey(์ฐธ์กฐํ ๋ชจ๋ธ,)
- ์๋ ์ฝ๋์์ host ํ๋๋ User ํ
์ด๋ธ์ ForeignKey๋ก ์ฐธ์กฐํ๊ณ ์๊ณ , room_type ํ๋๋ ๊ฐ์ Model์ ์๋ RoomType ํ
์ด๋ธ์ ์ฐธ์กฐํ๊ณ ์์ด์.
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models
from users import models as user_models
class AbstractItem(core_models.TimeStampedModel):
"""AbstractItem Object Definition"""
name = models.CharField(max_length=80)
class Meta:
abstract = True
def __str__(self):
return self.name
class RoomType(AbstractItem):
"""Room Type Model Definition"""
pass
class Room(core_models.TimeStampedModel):
"""Room Model Definifion"""
name = models.CharField(max_length=140)
description = models.TextField()
city = models.CharField(max_length=80)
country = CountryField()
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_out = models.TimeField()
check_in = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
room_type = models.ForeignKey(RoomType, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.name
2) on_delete ์ต์
- ForeignKey ํตํด์ ์์ฑ๋ ๊ฐ์ค์ด ์ด๋ค ํ ์ฌ์ฉ์๋ฅผ ๊ฐ๋ฅดํค๊ณ ์๋๋ฐ, ๋ง์ผ ์ฌ์ฉ์๊ฐ ํํด๋ฅผ ํ๋ค๋ฉด ํด๋น ๊ฐ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ด๋ป๊ฒํ ์ง ๊ฒฐ์ ํ๋ ๊ฒ์ด on_delete ์ต์
์ ๊ธฐ๋ฅ์ด์์.
- CASCADE : ์ฐธ์กฐ ๋์์ธ ๋ถ๋ชจ(์ฌ์ฉ์)๋ฅผ ์ญ์ ํ๋ฉด, ์ฐธ์กฐํ๊ณ ์๋ ์์(๊ฐ์ค)์ ์๋์ผ๋ก ์ญ์
- ๐ on_delete=models.CASCADE
- PROTECT : ์ฐธ์กฐ ์ค์ธ ์์(๊ฐ์ค)์ ๋ชจ๋ ์ญ์ ํ๊ธฐ ์ ์๋ ์ฐธ์กฐ ๋์์ธ ๋ถ๋ชจ(์ฌ์ฉ์)๋ฅผ ์ญ์ ํ ์ ์๋๋ก ๋ณดํธ
- ๐ on_delete=models.PROTECT
- SET_NULL : ์ฐธ์กฐ ๋์์ธ ๋ถ๋ชจ(์ฌ์ฉ์)๋ฅผ ์ญ์ ํ๋ฉด, ์ฐธ์กฐ ์ค์ธ ์์(๊ฐ์ค)์ ์ฐธ์กฐ๊ฐ Null์ ๊ฐ์ง๊ณ ์กด์ฌ
- ๐ on_delete=models.SET_NULL
- Default : ์ฐธ์กฐ ๋์์ธ ๋ถ๋ชจ(์ฌ์ฉ์)๋ฅผ ์ญ์ ํ๋ฉด, ์ฐธ์กฐ ์ค์ธ ์์(๊ฐ์ค)์ ์ค์ ํ Default๊ฐ๊ณผ ์ฐ๊ฒฐ
- ๐ on_delete=models.SET_DEFAULT
2. ManyToManyField
1) ManyToManyField ๋?
- ManyToManyField๋ ๋ค๋๋ค ๊ด๊ณ(many-to-many)๋ก ํ
์ด๋ธ์ ์ฐ๊ฒฐํ๊ณ ์ ํ ๋ ์ฌ์ฉํด์.
- ์๋ฅผ ๋ค์ด, 1๊ฐ์ ๊ฒ์๊ธ์ ์ฌ๋ฌ ๊ฐ์ tag๊ฐ ๋ฌ๋ฆด ์ ์๊ณ , ๋ํ ์ด๋ค ํ tag๋ ์ฌ๋ฌ ๊ฐ์ ๊ฒ์๊ธ์์ ์ฌ์ฉ๋ ๋ ์ฌ์ฉํด์.
- ManyToManyField ๊ด๊ณ๋ฅผ ํ๋๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด ๊ด๊ณ ์ฐ๊ฒฐ์ ์ํ ์ค๊ฐ ํ
์ด๋ธ(Intermediate Table)์ Django์์ ์๋์ผ๋ก ์์ฑํฉ๋๋ค.
2) room/models.py
- ManyToManyFiel ์ฌ์ฉ ๋ฐฉ๋ฒ
- ๐ ํ๋๋ช
= ManyToManyField(์ฐธ์กฐํ ๋ชจ๋ธ, blank=True)
from django.db import models
from django_countries.fields import CountryField
from core import models as core_models
from users import models as user_models
class AbstractItem(core_models.TimeStampedModel):
"""AbstractItem Object Definition"""
name = models.CharField(max_length=80)
class Meta:
abstract = True
def __str__(self):
return self.name
class RoomType(AbstractItem):
"""Room Type Model Definition"""
pass
class Amenity(AbstractItem):
"""Amenity Model Definition"""
pass
class Facility(AbstractItem):
"""Facility Model Definition"""
pass
class HouseRule(AbstractItem):
"""HouseRule Model Definition"""
pass
class Room(core_models.TimeStampedModel):
"""Room Model Definifion"""
name = models.CharField(max_length=140)
description = models.TextField()
city = models.CharField(max_length=80)
country = CountryField()
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_out = models.TimeField()
check_in = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
room_type = models.ForeignKey(RoomType, on_delete=models.CASCADE, null=True)
amenities = models.ManyToManyField(Amenity, blank=True)
facilities = models.ManyToManyField(Facility, blank=True)
house_rule = models.ManyToManyField(HouseRule, blank=True)
def __str__(self):
return self.name
3) room/admin.py
- Admin Panel์ ๋ํ๋๊ฒ ํ๊ธฐ ์ํด์๋ ์๋์ฒ๋ผ admin ๋ฑ๋ก์ ์งํ์์ผ์ฃผ์ด์ผ ํ์ฃ ,, ์ด๋ฅผ ํตํฉํ์ฌ ์์ฑํ ์ ๋ ์์ต๋๋ค.
from django.contrib import admin
from . import models
@admin.register(models.RoomType)
class ItemAdmin(admin.ModelAdmin):
pass
@admin.register(models.Amenity)
class AmenityAdmin(admin.ModelAdmin):
pass
@admin.register(models.Facility)
class FacilityAdmin(admin.ModelAdmin):
pass
@admin.register(models.HouseRule)
class HouseRuleAdmin(admin.ModelAdmin):
pass
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
pass
- ๋จ, ํ
์ด๋ธ์ด ๋น์ทํ ํน์ง์ ๊ฐ๊ณ ์๊ณ ์ถํ ๊ฐ๋ณ์ ์ธ Custom์ด ํ์์์ ๋๋ Admin์ ํตํฉํ์ฌ ๋ฑ๋กํ ์ ์์ด์:)
from django.contrib import admin
from . import models
@admin.register(models.RoomType, models.Amenity, models.Facility, models.HouseRule)
class ItemAdmin(admin.ModelAdmin):
pass
@admin.register(models.Room)
class RoomAdmin(admin.ModelAdmin):
pass
3. Sting ํํ๋ก ํ
์ด๋ธ ์ฐ๊ฒฐ
- Python์ ์ฝ๋๋ฅผ ์์์ ์๋๋ก ๋ฐฉํฅ์ผ๋ก ์ฝ์ด๋๊ฐ๊ธฐ ๋๋ฌธ์ ์ฐธ์กฐํ Class๊ฐ ์๋ ์์ผ๋ฉด ์ฝ์ด์ค์ง ๋ชปํ๋ค๋ ๋ฌธ์ ๊ฐ ์์ด์.
from django.db import models
from core import models as core_models
from users import models as user_models
class Photo(core_models.TimeStampedModel):
"""Photo Model Definition"""
caption = models.CharField(max_length=80)
file = models.ImageField()
room = models.ForeignKey(Room, on_delete=models.CASCADE)
class Room(core_models.TimeStampedModel):
"""Room Model Definifion"""
name = models.CharField(max_length=140)
description = models.TextField()
city = models.CharField(max_length=80)
country = CountryField()
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_out = models.TimeField()
check_in = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey(user_models.User, on_delete=models.CASCADE)
room_type = models.ForeignKey(RoomType, on_delete=models.CASCADE, null=True)
amenities = models.ManyToManyField(Amenity, blank=True)
facilities = models.ManyToManyField(Facility, blank=True)
house_rule = models.ManyToManyField(HouseRule, blank=True)
def __str__(self):
return self.name
- ์ด๋ฐ ๊ฒฝ์ฐ์, string์ผ๋ก ๋ณํํ์ฌ Model์ ์ฐ๊ฒฐ์ํค๋ฉด import๋ฅผ ํ์ง ์์๋ Django์์ ํด๋น Class๋ฅผ ์ค์ค๋ก ์ฐพ๊ณ , ์ฐธ์กฐํ Class๊ฐ ์๋ ์๋๋ผ๋ Django์์ ์์์ ์ฒ๋ฆฌํฉ๋๋ค:)
from django.db import models
from core import models as core_models
class Photo(core_models.TimeStampedModel):
"""Photo Model Definition"""
caption = models.CharField(max_length=80)
file = models.ImageField()
room = models.ForeignKey("Room", on_delete=models.CASCADE)
class Room(core_models.TimeStampedModel):
"""Room Model Definifion"""
name = models.CharField(max_length=140)
description = models.TextField()
city = models.CharField(max_length=80)
country = CountryField()
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_out = models.TimeField()
check_in = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey("users.User", on_delete=models.CASCADE)
room_type = models.ForeignKey("RoomType", on_delete=models.CASCADE, null=True)
amenities = models.ManyToManyField("Amenity", blank=True)
facilities = models.ManyToManyField("Facility", blank=True)
house_rule = models.ManyToManyField("HouseRule", blank=True)
def __str__(self):
return self.name
1) set์ ํตํ ์ ๊ทผ
- ForeignKey๋ก ์ด๋ค ํ
์ด๋ธ ๊ฐ๋ฅดํฌ ๊ฒฝ์ฐ, ์์ ํ
์ด๋ธ์ ํ๋๊ฐ์ผ๋ก ๋ถ๋ชจํ
์ด๋ธ๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํด์!
- ์ฆ, ForeignKey๋ก ๋ถ๋ชจ ํ
์ด๋ธ๋ฅผ ์ฐธ์กฐ์ค์ด๊ธฐ ๋๋ฌธ์ ํด๋น object์ ๋ชจ๋ ํ๋์ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค.
- _set์ ๋ฐ๋๋ก ๊ทธ object์์ ์์ ํ
์ด๋ธ์ ํ๋์ ์ ๊ทผํ๋ ๊ธฐ๋ฅ์ด์์.
- Room ๋ชจ๋ธ์ ์๋ host ํ๋(rooms/models.py)๊ฐ ForeignKey๋ฅผ ํตํด User ํ
์ด๋ธ์ ๊ฐ๋ฅดํค๋ฉด, User ๋ชจ๋ธ์ ๊ฐ object์์ "[๋ชจ๋ธ๋ช
]_set"์ผ๋ก ์์ ์ ๊ฐ๋ฅดํค๋ ๋ชจ๋ element์ ์ ๊ทผ์ด ๊ฐ๋ฅํฉ๋๋ค.
- ์ฆ, _set๋ ์์ ์ ์ฐธ์กฐํ๊ณ ์๋ object๋ก ์ ๊ทผํ๋ ๊ธฐ๋ฅ์ด์์:)
- ํ๋ ์์ฑ์ผ๋ก related_name์ ๊ฐ์ ์ง์ ํ๋ฉด, _set์ผ๋ก ์ ๊ทผํ๋ ๋์ ์ง์ ํ ๊ฐ์ผ๋ก ์ ๊ทผ์ด ๊ฐ๋ฅํด์.
- ๐ host = models.ForeignKey("users.User", related_name="rooms", on_delete=models.CASCADE)
class Room(core_models.TimeStampedModel):
"""Room Model Definifion"""
name = models.CharField(max_length=140)
description = models.TextField()
city = models.CharField(max_length=80)
country = CountryField()
price = models.IntegerField()
address = models.CharField(max_length=140)
guests = models.IntegerField()
beds = models.IntegerField()
bedrooms = models.IntegerField()
baths = models.IntegerField()
check_out = models.TimeField()
check_in = models.TimeField()
instant_book = models.BooleanField(default=False)
host = models.ForeignKey(
"users.User", related_name="rooms", on_delete=models.CASCADE
)
room_type = models.ForeignKey(
"RoomType", related_name="rooms", on_delete=models.CASCADE, null=True
)
amenities = models.ManyToManyField("Amenity", related_name="rooms", blank=True)
facilities = models.ManyToManyField("Facility", related_name="rooms", blank=True)
house_rule = models.ManyToManyField("HouseRule", related_name="rooms", blank=True)
def __str__(self):
return self.name
- ManyToManyField ๋ํ _set์ ์ด์ฉํ์ฌ ์์ ์ ๊ฐ๋ฅดํค๊ณ ์๋ object๋ก ์ ๊ทผํ ์ ์์ด์:)