📌 이 포스팅에서는 westatbucks ERM 모델링을 참고하여 Django의 Model을 작성하는 과정에 대해 정리하였습니다.
🔥 Model 파악하기
🔥 Model 생성하기
🔥 Create : Data 삽입
✔️ 목표 사이트 주소 : https://www.starbucks.co.kr/menu/drink_list.do
✔️ ERM 구성도
✔️ 앱을 생성하는 명령어는 startapp이다. 복수형으로 앱이름을 지정해주는 것이 권장된다.
$ python manage.py startapp [앱이름]
ex) $ python manage.py startapp products 👈 products앱 생성
✔️ 앱을 생성하였다면 등록해주어야 한다. 앱을 등록하지 않으면, Django에서 인식하지 못한다.
✔️ 앱을 등록시키는 방법은 간단하다. settgins.py에 앱이름만 등록해주면 된다.
✔️ "DJANGO_APPS", "PROJECT_APPS", "THIRD_PARTY_APPS"로 앱을 분리시킨 이유는 추후 복잡성을 낮추기 위함이다. 생성한 앱이나, 외부에서 설치하는 앱이 많지 않다면 분리시킬 필요가 없다.
# Application definition DJANGO_APPS = [ # "django.contrib.admin", # "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", ] PROJECT_APPS = [ "products", # 👈 products 앱을 등록합니다. ] THIRD_PARTY_APPS = [ "corsheaders", ] INSTALLED_APPS = DJANGO_APPS + PROJECT_APPS + THIRD_PARTY_APPS
✔️ products 앱을 생성하면 models.py는 자동으로 만들어져 있다. 이 곳에 테이블, 필드 등을 지정하고, 테이블간 relationship을 맺어주면 ORM구성도와 같이 모델을 구축할 수 있다.
✔️ Django뿐 아니라, 많은 프레임워크는 ORM을 지원하기 때문에 python 코드로 DB구축을 제어할 수 있어서 직접 SQL문을 작성하지 않아도 되기 때문에 간편하다.
✔️ models을 구성할 때는 class로 만들고, 이미 프레임워크에서 제공되는 models을 상속받아 사용한다.
from django.db import models class FirstModel(models.Model): # 👈 table 이름이 FirstModel일 때, pass
✔️ table은 Menu, Category, Product, Nutrition, Allergy, Image 테이블과 중계모델로 Allergy 테이블과 Product 테이블을 중계해주는 AllergyProduct을 생성했다.
✔️ 테이블을 생성할 때는 ForeignKey field가 필요하지 않은 모델부터 생성해서 점차 연결시켜나가면 구축하기 편하다.
✔️ Meta클래스를 통해 db_table의 이름을 지정하면, mysql에서 해당 이름으로 table이 생성된다.
# 🚀 Menu Table from django.db import models class Menu(models.Model): name = models.CharField(max_length=45) class Meta: db_table = "menu" # 🚀 Category Table class Category(models.Model): name = models.CharField(max_length=45) menu = models.ForeignKey("menu", on_delete=models.CASCADE) class Meta: db_table = "categories" # 🚀 Product Table class Product(models.Model): name = models.CharField(max_length=45) category = models.ForeignKey("Category", on_delete=models.CASCADE) nutrition = models.ForeignKey("Nutrition", on_delete=models.CASCADE) allergy = models.ManyToManyField("Allergy", through="AllergyProduct") class Meta: db_table = "products" # 🚀 Nutrition Table class Nutrition(models.Model): kcal = models.DecimalField(max_digits=5, decimal_places=2, default=0) sodium = models.DecimalField(max_digits=5, decimal_places=2, default=0) fat = models.DecimalField(max_digits=5, decimal_places=2, default=0) sugar = models.DecimalField(max_digits=5, decimal_places=2, default=0) protein = models.DecimalField(max_digits=5, decimal_places=2, default=0) caffeine = models.DecimalField(max_digits=5, decimal_places=2, default=0, null=True) class Meta: db_table = "nutritions" # 🚀 Allergy Table class Allergy(models.Model): name = models.CharField(max_length=45) class Meta: db_table = "allergies" # 🚀 AllergyProduct Table class AllergyProduct(models.Model): product = models.ForeignKey("Product", on_delete=models.CASCADE) allergy = models.ForeignKey("Allergy", on_delete=models.CASCADE, null=True) class Meta: db_table = "allergies_products" # 🚀 Image Table class Image(models.Model): image_url = models.CharField(max_length=2000) product = models.ForeignKey("Product", on_delete=models.CASCADE) class Meta: db_table = "images"
✔️ 모델을 구성햇다면, 이를 통해 MySQL에 모델을 생성해주기 위해 2가지 명령이 필요하다.
✔️ 이를 makemigration과 migrate이다. 한번에 명령하는 방법은 아래와 같다.
✔️ models.py의 변경이 일어났다면, 이 명령어를 잊지 말고 실행시켜주자.
$ python manage.py makemigration && python manage.py migrate
✔️ 터미널에서 Mysql에 접속한하여 확인할 DB를 선택한다.
$ mysql -u root -p 👈 login
$ show databases; 👈 DB목록 조회
$ use [목록 중 확인할 db명]; 👈 DB 선택
✔️ 해당 DB에 생성된 table을 확인한다.
$ show tables; 👈 DB 선택
& desc [확인할 table명] 👈 table이 어떤 구조로 생성되었는지 보여준다.
✔️ 해당 table의 데이터 확인은 아래와 같다. 데이터가 있어야 확인된다.
& select * from [확인할 table명]
✔️ 모든 컬럼(필드)이 아닌 일부만 조회하고 싶다면 아래와 같이 할 수 있다.
& select [field명, field명, field명...] from [확인할 table명]
✔️ 데이터를 삽입하다보면 잘못 저장되는 생성되는 실수가 발생한다. 해당 row만 삭제하면 순번 건너띄기가 발생하기 때문에 필요에 따라 table을 초기화하고 싶을 때가 있다. 이럴 때는 아래 명령으로 가능하다.
& truncate [table명] 👈 table을 삭제하고 다시 생성해주는 명령을 한번에 가능하게 해준다.
✔️ 해당 table에 ForeignKey가 존재가 존재하거나, 참조받고 있다면 이러한 "ERROR 1701 (42000)"가 발생한다. mysql에서 보호를 목적으로 lock을 걸어둔거 같다.
✔️ 이럴 때는 외래키 체크 해제를 해주고 해당 명령어를 사용해주면 정상적으로 동작한다. 테이블을 초기화하고 다시 외래키를 활성화시키는게 안전하다.
& SET FOREIGN_KEY_CHECKS = 0; 👈 외래키 체크 해제
$ SET FOREIGN_KEY_CHECKS = 1; 👈 외래키 체크 설정
✔️ DB에 data를 삽입하기 위해서 Django shell에 진입합니다.
& python manage.py shell
✔️ Menu Table data 삽입
# python manage.py shell >>> Menu.objects.create(name="음료") >>> Menu.objects.create(name="푸드") >>> Menu.objects.create(name="상품") >>> Menu.objects.create(name="카드")
✔️ Category Table data 삽입
# python manage.py shell >>> m1 = Menu.objects.get(id=1) >>> m2 = Menu.objects.get(id=2) >>> Category.objects.create(name="콜드 브루", menu_id=m1) >>> Category.objects.create(name="브렌디드", menu_id=m1) >>> Category.objects.create(name="브레드", menu_id=m2) >>> Category.objects.create(name="케이크", menu_id=m2)
✔️ Nutrition Table data 삽입
# python manage.py shell >>> Nutrition.objects.create(kcal=75, sodium=20, fat=2, sugar=10, protein=1, caffeine=245) >>> Nutrition.objects.create(kcal=5, sodium=5, caffeine=245) >>> Nutrition.objects.create(kcal=120, sodium=70, fat=0, sugar=25, protein=1, caffeine=35) >>> Nutrition.objects.create(kcal=370, sodium=105, fat=4.3, sugar=57, protein=9) >>> Nutrition.objects.create(kcal=468, sodium=487, fat=13, sugar=16, protein=8) >>> Nutrition.objects.create(kcal=395, sodium=270, fat=12, sugar=11, protein=4) >>> Nutrition.objects.create(kcal=375, sodium=340, fat=4, sugar=18, protein=5)
✔️ Product Table data 삽입
# python manage.py shell >>> c1 = Category.objects.get(id=1) >>> c2 = Category.objects.get(id=2) >>> c3 = Category.objects.get(id=3) >>> c4 = Category.objects.get(id=4) >>> n1 = Nutrition.objects.get(id=1) >>> n2 = Nutrition.objects.get(id=2) >>> n3 = Nutrition.objects.get(id=3) >>> n4 = Nutrition.objects.get(id=4) >>> n5 = Nutrition.objects.get(id=5) >>> n6 = Nutrition.objects.get(id=6) >>> n7 = Nutrition.objects.get(id=7) >>> Product.objects.create(name="나이트로 바닐라 크림", description="생략", category_id=c1, nutrition_id=n1) >>> Product.objects.create(name="나이트로 콜드 브루", description="생략", category_id=c1, nutrition_id=n2) >>> Product.objects.create(name="망고 패션 프로트 브렌디드", description="생략", category_id=c2, nutrition_id=n3) >>> Product.objects.create(name="딸기 딜라이트 요거트 브렌디드", description="생략", category_id=c2, nutrition_id=n4) >>> Product.objects.create(name="미니 클래식 스콘", description="생략", category_id=c3, nutrition_id=n5) >>> Product.objects.create(name="밀당 에그 타르트", description="생략", category_id=c4, nutrition_id=n6) >>> Product.objects.create(name="밀당 초코 타르트", description="생략", category_id=c4, nutrition_id=n7)
✔️ Image Table data
# python manage.py shell >>> p1 = Product.objects.get(id=1) >>> p2 = Product.objects.get(id=2) >>> p3 = Product.objects.get(id=3) >>> p4 = Product.objects.get(id=4) >>> p5 = Product.objects.get(id=5) >>> p6 = Product.objects.get(id=6) >>> p7 = Product.objects.get(id=7) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p1) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p2) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p3) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p4) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p5) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p6) >>> Image.objects.create(image_url="이미지 경로 복사 주소", product_id=p7)
✔️ Allergy Table data
# python manage.py shell >>> Allergy.objects.create(name="대두") >>> Allergy.objects.create(name="우유") >>> Allergy.objects.create(name="난류") >>> Allergy.objects.create(name="밀") >>> Allergy.objects.create(name="아항산류") >>> Allergy.objects.create(name="토마토")
✔️ AllergyProduct Table data
# python manage.py shell >>> a1 = Allergy.object.get(id=1) >>> a2 = Allergy.object.get(id=2) >>> a3 = Allergy.object.get(id=3) >>> a4 = Allergy.object.get(id=4) >>> a5 = Allergy.object.get(id=5) >>> a6 = Allergy.object.get(id=6) >>> p1 = Product.objects.get(id=1) >>> p2 = Product.objects.get(id=2) >>> p3 = Product.objects.get(id=3) >>> p4 = Product.objects.get(id=4) >>> p5 = Product.objects.get(id=5) >>> p6 = Product.objects.get(id=6) >>> p7 = Product.objects.get(id=7) >>> AllergyProduct.objects.create(allergy_id=a2, product_id=p1) >>> AllergyProduct.objects.create(allergy_id=a2, product_id=p4) >>> AllergyProduct.objects.create(allergy_id=a2, product_id=p5) >>> AllergyProduct.objects.create(allergy_id=a3, product_id=p5) >>> AllergyProduct.objects.create(allergy_id=a4, product_id=p5) >>> AllergyProduct.objects.create(allergy_id=a2, product_id=p6) >>> AllergyProduct.objects.create(allergy_id=a3, product_id=p6) >>> AllergyProduct.objects.create(allergy_id=a1, product_id=p6) >>> AllergyProduct.objects.create(allergy_id=a1, product_id=p7) >>> AllergyProduct.objects.create(allergy_id=a2, product_id=p7) >>> AllergyProduct.objects.create(allergy_id=a3, product_id=p7) >>> AllergyProduct.objects.create(allergy_id=a4, product_id=p7)
역시 최고