(TIL19) 스타벅스 모델링

SooHyung Kim·2020년 4월 18일
0

Today I learned

목록 보기
16/25

스타벅스 음료 부문 모델링 진행

모델링

  1. 메뉴 > 카테고리, 카테고리 > 제품 간은 일대다 관계를 설정
    (한 개의 메뉴는 여러 개의 카테고리를 가지므로)

    • 특히, 제품은 본인의 PK 외에 메뉴의 ID와 카테고리의 ID를 FK로 받아 옴
  2. 제품과 음료의 사이즈의 관계는 일대일 관계를 설정
    (하나의 제품은 하나의 사이즈만을 가지고 있으므로(홈페이지 상))

  3. 제품과 알레르기 유발요인 간에는 다대다 관계를 설정
    (하나의 제품은 여러 개의 알레르기 유발 요인을 가지며 반대로 알레르기 역시 다수의 제품의 요인으로 작용할 수 있기 때문)

    • 제품과 알레르기 유발요인 간 중간 테이블을 설정하여 다:1, 1:다 관계의 매핑을 진행

위의 사진을 토대로 장고 앱 내의 models.py에 다음과 같이 정의

from django.db import models

class Category(models.Model):
    name    = models.CharField(max_length = 100)

    class Meta:
        db_table = 'categories'

class Product_to_Category(models.Model):
    menu_id     = models.ForeignKey(Category, on_delete = models.CASCADE)
    product_id  = models.IntegerField

    class Meta:
        db_table = "product_to_category"

class Size_amount(models.Model):
    size   = models.CharField(max_length = 45)
    ml     = models.IntegerField
    floz   = models.IntegerField

    class Meta:
        db_table = "size_amount"

class Product(models.Model):
    category         = models.ForeignKey(Category, on_delete = models.CASCADE)
    product_id       = models.ForeignKey(Product_to_Category, on_delete=models.CASCADE)
    size             = models.ForeignKey(Size_amount, on_delete=models.CASCADE)
    product_name     = models.CharField(max_length = 100)
    product_eng_name = models.CharField(max_length = 100)
    description      = models.TextField
    image            = models.ImageField
    pre_image        = models.ImageField
    calory           = models.FloatField
    saturated_fat    = models.FloatField
    protein          = models.FloatField
    sodium           = models.FloatField
    sugar            = models.FloatField
    caffeine         = models.FloatField

    class Meta:
        db_table = "product"

class Allergy(models.Model):
    name   = models.CharField(max_length = 45)

    class Meta:
        db_table = "allergy"

class Allergy_Product(models.Model):
    allergy  = models.ForeignKey(Allergy, on_delete = models.CASCADE)
    product  = models.ForeignKey(Product, on_delete = models.CASCADE)

    class Meta:
        db_table = "allergy_product"

Solution

  • 우리 조에서 진행한 모델링 외 멘토님의 모델링으로 수업이 진행
class Menu(models.Model):
    name        =   models.CharField(max_length = 10)

    class Meta:
        db_table = 'menus'
python shell
>> Menu.objects.create(name="음료")
  • 클래스 내부에 Meta 클래스를 추가하여 메타데이터를 추가하며, 데이터베이스 내의 테이블 명을 복수로 지정
class Category(models.Model):
    name        =   models.CharField(max_length = 50)
    menu        =  models.ForeignKey(Menu, on_delete=models.SET_NULL, null = True)
   
    class Meta:
        db_table = 'categories'
python shell
Category.objects.create(name="콜드브루커피",menu_id=1)
  • ForeignKey(to, on_delete)

    • to : menu의 경우처럼 외래키 호출 시 클래스명 자체를 삽입하면 이미 선언된 클래스를 지정하며, '클래스명' 으로 삽입하면 아직 선언되지 않은 클래스도 지정이 가능

    • on_delete : 참조하고 있는 테이블이 삭제가 되면 어떻게 할 것인지 결정

      • CASCADE : 상위 테이블이 삭제되면 컬럼에 있는 데이터가 삭제됨
      • SET_NULL : 외래키 지정되었던 컬럼만 null로 수정되고 데이터 자체는 살아 있음(실무에서 많이 사용됨)
    • python shell에서 자료를 생성할 때에는 Category.objects.create(name='콜드브루커피', menu_id=1)와 같이 뒤에 _id를 넣어 생성

class Drink(models.Model):
    name          = models.CharField(max_length=50)
    menu          = models.ForeignKey(Menu, on_delete=models.SET_NULL, null=True)
    category      = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
    nuturition    = models.OneToOneField('Nutrition', on_delete=models.SET_NULL, null=True)
    allergy_drink = models.ManyToManyField('Allergy', through = 'AllergyDrink')

    class Meta:
        db_table = 'drinks'
allergy_drink에 값을 입력하는 방법
>> and = Drink.objects.get(id=1)
>> and.allergy_drink.add(Allergy.objects.get(id=1), Allergy.objects.get(id=2))
  • 테이블 간의 관계가 one to many일 경우 외래키, one to one 일 때는 onetoonefield
  • 테이블 간의 관계가 many to many일 경우 장고에서는 이를 인식하고 적절한 다대다 테이블을 자체적으로 생성하나, through='중간테이블'을 명령을 통해 개발자가 직접 통제하는 것이 훨씬 유리(추가적인 필드 생성 등)
class Nutrition(models.Model):
    # decimal : 금액, 지도상 좌표 등을 표현할 때 주로 사용
    one_serving_kcal    = models.DecimalField(max_digits=10, decimal_places=2)
    sodium_mg           = models.DecimalField(max_digits=10, decimal_places=2)
    saturated_fat_g     = models.DecimalField(max_digits=10, decimal_places=2)
    sugars_g            = models.DecimalField(max_digits=10, decimal_places=2)
    proteing_g          = models.DecimalField(max_digits=10, decimal_places=2)
    caffeine_mg         = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        db_table = 'nutritions'

class Image(models.Model):

    image_url   =  models.URLField(max_length = 2000)
    drink       =  models.ForeignKey(Drink, on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = 'images'
  • image_url을 imagefield로 지정해도 무관하나 본 필드는 장고 2세대 전용으로 URLField가 더 적절하며, 기능은 url 넣으면 주소만 저장하는 기능을 가짐
class Description(models.Model):
    description  = models.CharField(max_length=1000)
    drink       =  models.ForeignKey(Drink, on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = 'descriptions'

class Size(models.Model):
    name = models.CharField(max_length = 45)
    size_ml = models.IntegerField(default = 0)
    size_fluid_ounce = models.IntegerField(default = 0)
    nutrition = models.ForeignKey(Nutrition, on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = 'sizes'

class Allergy(models.Model):
    name    = models.CharField(max_length = 50)

    class Meta:
        db_table = 'allergies'


class AllergyDrink(models.Model):
    allergy = models.ForeignKey(Allergy, on_delete=models.SET_NULL, null=True)
    drink   = models.ForeignKey(Drink, on_delete=models.SET_NULL, null=True)

    class Meta:
        db_table = 'allergydrinks'
  • Allergy 테이블과 Drink 테이블 간의 중간 테이블을 생성하며, 각각의 요소를 FK로 받음
profile
Slow and steady win the race

0개의 댓글