스타벅스 음료 데이터베이스

Jina·2020년 4월 13일
0

Django

목록 보기
6/11

스타벅스 음료 카테고리 데이터베이스 짜기

위의 데이터베이스를 django로 모델링하기

app이름은 starbucks로 만들었음

내가 짠 모델링

from django.db import models

class Menu(models.Model):
    menu_name=models.CharField(max_length=45)
    
class Category(models.Model):
    menu=models.ForeignKey(Menu, on_delete=models.CASCADE)
    category_name=models.CharField(max_length=45)
    
class NutritionInformation(models.Model):
    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)
    protein_g=models.DecimalField(max_digits=10,decimal_places=2)
    caffeine_mg=models.DecimalField(max_digits=10,decimal_places=2)
    
class Drink(models.Model):
    category=models.ForeignKey(Category, on_delete=models.CASCADE)
    drink_name=models.CharField(max_length=45)
    nutrition=models.ForeignKey(NutritionInformation, on_delete=models.CASCADE)
    
class Size(models.Model):
    nutrition=models.ForeignKey(NutritionInformation, on_delete=models.CASCADE)
    size_name=models.CharField(max_length=45)
    size_ml=models.IntegerField(max_length=30)
    size_fluid_ounce=models.IntegerField(max_length=30)
    
class Image(models.Model):
    drink=models.ForeignKey(Drink, on_delete=models.CASCADE)
    image_url=models.CharField(max_length=2000)
    
class Description(models.Model):
    drink=models.ForeignKey(Drink, on_delete=models.CASCADE)
    description=models.CharField(max_length=1000)
  
class Allergy(models.Model):
    allergy_ingredient=models.CharField(max_length=45)
    
class AllergyDrink(models.Model):
    allergy=models.ForeignKey(Allergy, on_delete=models.CASCADE)
    drink=models.ForeignKey(Drink, on_delete=models.CASCA

solution

해줘야 할 것

1. class Meta

모델링한 클래스 아래에

class Meta:
	db_table = "table_name"

추가해주기

이 때 테이블 명은 복수로

2. ForeignKey class명

ForeignKey(class명 또는 스트링명, on_delete)
위와 같이 사용하는데 class명을 쓸 때 class명 또는 'class명'으로 사용

차이는? class명만 사용할 때는 이미 위에서 선언된 class명
'class명' 사용은 아직 선언되지 않았지만 언젠가는 선언될 class명 때 사용함

그냥 'class명'으로 쓰는게 마음이 편함

예시 1) class명 사용할 때

nutrition=models.ForeignKey(NutritionInformation, on_delete=models.SET_NULL,null=True)

예시 2) 'class명' 사용할 때

nutrition=models.ForeignKey('NutritionInformation', on_delete=models.SET_NULL,null=True)

3. on delete

참조하고 있는 요소가 삭제되었을 때 어떻게 처리할지

3-1. on delete=models.CASCADE

참조하고 있는 요소가 삭제되었을 때 (상위 존재가 삭제되었을 때) 하위 데이터 전부 지우기
ex) 만약 category에 콜드브루가 지워지면, 콜드브루를 참조하고 있던 음료들이 모두 지워짐

3-2. on delete=models.SET_NULL, null=True

참조하고 있는 요소가 삭제되었을 때 참조하고 있는 데이터 부분만 null로 처리
데이터가 다 지워지지 않아서 데이터가 보호됨 필요없는 데이터가 아닌 이상 보통 SET_NULL사용

이때 null=True를 지정해주어야함 (기본값이 null=False기 때문에)

4. 참조키

ForeignKey --> one to many 의미
OneToOneField --> one to one 의미
ManyToManyField --> Many to Many 의미

5. ManyToManyField 주의 사항

ManyToMany 필드 사용할 때 그냥 사용하면 장고가 중간 데이터 필드를 처리함
이 경우는 내가 중간 데이터 등을 컨트롤하기 힘듬

중간 테이블을 만들어서 사용하는 것이 컨트롤하기 좋음 --> 따라서 중간 테이블 만들기

중간 테이블 만들고 바로 중간 테이블 연결해주려면 throgh사용하기
사용 예시는 아래의 class Drink에서 확인하기

solution

from django.db import models

class Menu(models.Model):
     menu_name=models.CharField(max_length=45)

     class Meta:
          db_table = 'menus'

 class Category(models.Model):
      menu=models.ForeignKey('Menu', on_delete=models.SET_NULL, null=True)  
      category_name=models.CharField(max_length=45)

      class Meta:
          db_table = 'categories'


class NutritionInformation(models.Model):
     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)
     protein_g=models.DecimalField(max_digits=10,decimal_places=2)
     caffeine_mg=models.DecimalField(max_digits=10,decimal_places=2)

     class Meta:
         db_table = 'nutritoninformations'


class Drink(models.Model):
     category=models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
     drink_name=models.CharField(max_length=45)
     nutrition=models.OneToOneField('NutritionInformation', on_delete=SET_NULL, null=True)
     menu=models.ForeignKey('Menu', on_delete=models.SET_NULL, null=True)
     allergydrink=models.ManyToManyField('Allergy', through='AllergyDrink')

# Drink에서 바로 알러지 참조가 가능
# 중간 테이블 필요
# 중간 테이블 through='AllergyDrink' --> AllergyDrink에서 하는 일을 여기서 하겠다는 의미 / 중간 테이블 만들면 테이블 관리 편함
# through를 사용하지 않으면 장고에서 임의로 테이블 만들어서 사용 --> 이 경우는 중간 테이블 관리 어려움 
     class Meta:
         db_table = 'drinks'

class Size(models.Model):
     nutrition=models.ForeignKey('NutritionInformation', on_delete=models.SET_NULL,null=True)
     size_name=models.CharField(max_length=45)
     size_ml=models.IntegerField(default=0)
     size_fluid_ounce=models.IntegerField(default=0)
	
    # defualt=0은 초기값
    
    class Meta:
        db_table = 'sizes'


 class Image(models.Model):
     drink=models.ForeignKey('Drink', on_delete=models.SET_NULL, null=True
     image_url=models.URLField(max_length=2000)

     class Meta:
         db_table='images'
     

class Description(models.Model):
     drink=models.ForeignKey('Drink', on_delete=models.SET_NULL, null=True)
     description=models.CharField(max_length=1000)

     class Meta :
         db_table='descriptions'


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

     class Meta:
         db_table = 'allergies'
         

 # AllergyDrink --> 중간테이블
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'

shell에서 데이터 다루기

위의 내용을 migration하고 shell에서 확인해보기

ForeignKey 사용할 때

Category.objects.create(category_name='콜드 브루 커피', menu_id=1)
위의 예시 menu_id=1 와 같이 id를 배정해줌

menu_id에서 menu는 class내의 데이터이름
menu_id가 class Category에 데이터베이스 필드명

(class명 Menu의 id=1이 아니라 Category class의 menu라는 데이터 / 여기서 menu데이터는 Menu class와 Foreignkey로 연결되어있음 )

ManyToMany에서 데이터 추가하기

drink table에 allergydrink (ManyToMany로 연결되어있음) 를 추가하려면 일반적인 방법처럼 추가할 수 없음

방법1. allergydrink 테이블에 입력하기

allergydrink 테이블에 allergy의 id와 drink의 id를 입력해주어야함

방법 2. drink 테이블에서 처리하기텍스트

drink 테이블에 객체로 전달해주는 방법
이 방법이 좀 더 편리함 (데이터가 많아질수록 편리함)

아래의 예시와 같이 데이터 추가할 수 있음

예시)

drink = Drink.objects.get(id=1)
drink.allergydrink.add(Allergy.objects.get(id=2))

drink안의 allergydrink 불러와서 여기에 Allergy.objects.get(id=2)라는 객체를 추가해주는 형식 (allergies 테이블에 데이터 미리 추가되어있어야함)

여기서 drink는 id=1로 확정된 상태, 알레르기의 id=2의 데이터를 가지고와서 이 데이터를 추가해주는 느낌

여러개의 알레르기를 입력하고 싶을 때

여러개의 알레르기를 입력하고 싶을 때는 아래와 같이 입력

drink = Drink.objects.get(id=1)
drink.allergydrink.add(Allergy.objects.get(id=2))
drink.allergydrink.add(Allergy.objects.get(id=3))

0개의 댓글