1. Django Tutorial(Airbnb) - ForeignKey & ManyToManyField

ID์งฑ์žฌยท2021๋…„ 8์›” 2์ผ
0

Django

๋ชฉ๋ก ๋ณด๊ธฐ
13/43
post-thumbnail

๐ŸŒˆ 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
# Create your models here.
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) # ๐Ÿ‘ˆ ForeignKey
    room_type = models.ForeignKey(RoomType, on_delete=models.CASCADE, null=True) # ๐Ÿ‘ˆ ForeignKey
    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
# Create your models here.
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) # ๐Ÿ‘ˆ ManyToManyField
    facilities = models.ManyToManyField(Facility, blank=True) # ๐Ÿ‘ˆ ManyToManyField
    house_rule = models.ManyToManyField(HouseRule, blank=True) # ๐Ÿ‘ˆ ManyToManyField
    def __str__(self):
        return self.name

3) room/admin.py

  • Admin Panel์— ๋‚˜ํƒ€๋‚˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ admin ๋“ฑ๋ก์„ ์ง„ํ–‰์‹œ์ผœ์ฃผ์–ด์•ผ ํ•˜์ฃ ,, ์ด๋ฅผ ํ†ตํ•ฉํ•˜์—ฌ ์ž‘์„ฑํ•  ์ˆ˜ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.
from django.contrib import admin
from . import models
# Register your models here.
@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
# Register your models here.
@admin.register(models.RoomType, models.Amenity, models.Facility, models.HouseRule)
class ItemAdmin(admin.ModelAdmin):
    pass
@admin.register(models.Room) # ๐Ÿ‘ˆ ๋ณ„๋„์˜ Custom์„ ์ ์šฉ์‹œํ‚ฌ ํ…Œ์ด๋ธ”์„ ํ†ตํ•ฉ์‹œํ‚ค์ง€ ์•Š์•„์š”:)
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
# Create your models here.
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) # ๐Ÿ‘ˆ ๋ฐ”๋กœ ์•„๋ž˜ Room์„ ์ธ์‹๋ชปํ•จ   
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
# from users import models as user_models # ๐Ÿ‘ˆ ํ•„์š” ์—†์Œ
# Create your models here.
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) # ๐Ÿ‘ˆ string์œผ๋กœ ์—ฐ๊ฒฐ
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)
    # ๐Ÿ‘‡ string์œผ๋กœ ์—ฐ๊ฒฐ
    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๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์–ด์š”:)
profile
Keep Going, Keep Coding!

0๊ฐœ์˜ ๋Œ“๊ธ€