장고 - 별다방 저장소
장고와 MySQL을 이용한 API를 만들어보자.
미니콘다를 이용한 가상환경에서 진행을 하기 위해 우선 가상환경부터 셋팅을 진행하자.
나는 바탕화면에서 프로젝트 폴더를 만드는 것을 좋아한다 :) 바로 눈에 보여서 심신이 편안하다.
프로젝트 이름은 "westarbucks". 이제 나도 스타벅스 입문자.
아래 캡쳐와 같이 진행을 했다.
대중성을 위하여 파이썬 3.8버전으로 진행하였다.
이후, westarbucks 로 옮긴 후 장고를 설치해 주었다.
필요한 플러그인들을 설치해 준 후, 장고 프로젝트 생성!
참고) starbucks 뒤에
띄어쓰기.
을 입력하면 현재 파일에서 프로젝트가 생성된다.
셋팅을 완료하기 위해서 추가적인 플러그인을 설치해서 settings에 임폴트 후 셋팅을 진행했다.
또한, 별다방의 비밀스러움을 위해 시크릿키와 데이터베이스의 정보를 my_settings.py 로 옮겨 준 후
settings.py에서 my_settings.py를 import 해서 SECRET_KEY = SECRET_KEY / DATABASES = DATABASES
로 설정해주었다.
한번 실행해볼까요?
python manage.py runserver
잘 실행되었다. 이후 git을 해주기 위해서 git 설정을 진행했다. git의 셋팅방법등의 자세한 내용은 git 챕터를 확인하자.
git을 설정한 후 이제 products 라는 이름으로 앱을 설정하기 위해서 python manage.py startapp products
을 진행했는데, 갑자기 에러가 발생했다.
에러의 내용은 아래 코드와 같다.
python manage.py startapp products
Traceback (most recent call last):
File "manage.py", line 22, in <module>
main()
File "manage.py", line 18, in main
execute_from_command_line(sys.argv)
...
...
File "<frozen importli
b._bootstrap>", line 1014, in _gcd_import
File "<frozen importlib._bootstrap>", line 991, in _find_and_load
File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'products'
이게 무슨 일인가 했더니 settings.py / INSERT_APP
에서 미리 'products'를 넣어버려서 난 오류였다. 그래서 내용을 주석처리하고 다시 진행했더니 정상적으로 진행됐다...
startapp 이후 settings.py 설정..메모..메모..
작고 소중한 별다방을 위해서 이제 모델을 만들어주자. database에는 메뉴, 카테고리, 음료, 알러지, 알러지_음료, 영양정보, 사진, 사이즈(음료)
가 필요할 것 같다. 카테고리에는 빵이나 상품 등 여러 종류가 더 있지만, 지금은 음료만 구현하기로 했다.
이제 models.py 에서 database의 테이블을 만들어주자 :-) 기능은 쓰라고 있는 거니깐!
from django.db import models
# Create your models here.
class Menu(models.Model):
name = models.CharField(max_length=45)
class Meta:
db_table = 'menus'
class Category(models.Model):
name = models.CharField(max_length=45)
menu = models.ForeignKey('Menu', on_delete=models.CASCADE)
class Meta:
db_table = 'categories'
class Drink(models.Model):
korean_name = models.CharField(max_length=45)
english_name = models.CharField(max_length=45)
description = models.TextField()
category = models.ForeignKey('Category', on_delete=models.CASCADE)
class Meta:
db_table = 'drinks'
class Images(models.Model):
image_url = models.CharField(max_length=2000)
drink = models.ForeignKey('Drink', on_delete=models.CASCADE)
class Meta:
db_table = 'images'
class Allergy(models.Model):
name = models.CharField(max_length=45)
drinks = models.ManyToManyField('Drink', through='AllergyOfDrink', through_fields=('allergy', 'drink'))
class Meta:
db_table = 'allergies'
class AllergyOfDrink(models.Model):
allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE)
drink = models.ForeignKey('Drink', on_delete=models.CASCADE)
class Meta:
db_table = 'allergy_drink'
class Size(models.Model):
name = models.CharField(max_length=45)
size_ml = models.CharField(max_length=45)
size_fluid_ounce = models.CharField(max_length=45)
drinks = models.ManyToManyField('Drink', through='Nutrition', through_fields=('size', 'drink'))
class Meta:
db_table = 'sizes'
class Nutrition(models.Model):
one_serving_kca = 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)
drink = models.ForeignKey('Drink', on_delete=models.CASCADE)
size = models.ForeignKey('Size', on_delete=models.CASCADE)
class Meta:
db_table = 'nutritions'
하나씩...써야 한다. 하지만 지금은 코드만 적어놓는다.
주의깊게 살펴봐야 하는 것은 ForeignKey 부분과 ManyToManyField 부분이다. 1:N, N:M 관계를 함수들인데 곧 자세히 작성할 예정이다. 장고의 ORM과 RDMBS, RDB, DMBS 등 추가적으로 공부하고 작성해야 할 내용이 저~~~엉말 많다. 행복하다 :-)))))))
하여튼, migration을 만들어주고 migrate로 MySQL로 올려줬다.
이제...각 테이블에 맞게...manage.py shell 을 이용해서...... data를 넣어주자....
스타벅스 홈페이지 한국판이다. 순서에 맞게 우선 menus
에는 음료, 푸드, 상품을 넣어주자.
쉘에서 아래 캡쳐처럼 입력을 진행했다.
후에 MySQL에서 잘 들어갔는지 확인을 해줬다. 빠트리면 안되니깐 :-)
잘 들어간 것을 확인했다.
앞으로 위와 같은 방식으로 categories
부터 시작해서 sizes
까지 쭉쭉쭉 입력할 예정이다.
....반복문으로 쉽게 하는 방법이 없을까 고민을 시작했다....
아직은..좋은 생각이 떠오르지 않기에 단순 작업을 시작해주기로 하였다.
ForeignKey를 가진 테이블들은 위 방법과는 다르게 kwargs를 하나 더 줘야 한다. 바로 정참조를 하고 있는 테이블을 알려줘야한다. create 하는 방법은 여러가진데, 그 중 하나인 bulk를 이용하기로 했다. 이러면 더 빠를 거 같아서 ㅎㅎㅎ
a = Menu.objects.get(name="음료")
Category.objects.bulk_create([Category(name="콜드 브루", menu=a), Category(name="브루드 커피", menu=a), Category(name="에스프레소", menu=a), Category(name="프라푸치노", menu=a), Category(name="블렌디드", menu=a), Category(name="스타벅스 피지오", menu=a), Category(name="티(티바나)", menu=a), Category(name="기타 제조 음료", menu=a), Category(name="스타벅스 주스(병음료)", menu=a)])
name = "" / menu = a
일 때 menu 는 models.py 에 들어있는 각각의 클래스의 포린키가 대입된 변수명이다. 헷갈리면 안된다.
잘 들어갔나 다시 한번 확인!
잘 들어갔다 :)
계속 작성해보자. 이번엔 drinks
다.
b = Category.objects.get(id=1)
Drink.objects.bulk_create([Drink(korean_name="나이트로 바닐라 크림", english_name="Nitro Vanilla Cream", description="soft vanila", category=b), Drink(korean_name="나이트로 콜드 브루", english_name="Nitro Cold Brew", description="nitro cold", category=b), Drink(korean_name="돌체 콜드 브루", english_name="Dolce Cold Brew", description="Dolce cold", category=b), Drink(korean_name="바닐라 크림 콜드 브루", english_name="Vanilla Cream Cold Brew", description="cold vanilla", category=b), Drink(korean_name="벨벳 다크 모카 나이트로", english_name="Velvet Dark Mocha Nitro", description="dark mocha", category=b), Drink(korean_name="시그니처 더 블랙 콜드 브루", english_name="Signature The Black Cold Brew", description="black cold", category=b), Drink(korean_name="제주 비자림 콜드 브루", english_name="Jeju Forest Cold Brew", description="forest cold", category=b), Drink(korean_name="콜드 브루", english_name="Cold Brew", description="original cold", category=b), Drink(korean_name="콜드 브루 몰트", english_name="Cold Brew Malt", description="cold malt", category=b), Drink(korean_name="콜드 브루 오트 라떼", english_name="Cold Brew With oat Milk", description="health", category=b), Drink(korean_name="콜드 브루 플로트", english_name="Cold Brew Float", description="icecream", category=b), Drink(korean_name="프렌치 애플 타르트 나이트로", english_name="French Apple Tarte Nitro", description="apple cold", category=b)])
c = Category.objects.get(id=2)
Drink.objects.bulk_create([Drink(korean_name="아이스 커피", english_name="Iced Coffee", description="normal", category=c), Drink(korean_name="오늘의 커피", english_name="Brewed Coffee", description="today brewed", category=c)])
d = Category.objects.get(id=3)
Drink.objects.bulk_create([Drink(korean_name="에스프레소 콘 파나", english_name="Espresso Con Panna", description="i don'k know", category=d), Drink(korean_name="에스프레소 마키아또", english_name="Espresso Macchiato", description="idk", category=d), Drink(korean_name="아이스 카페 아메리카노", english_name="Iced Caffe Americano", description="idk", category=d), Drink(korean_name="카페 아메리카노", english_name="Caffe Americano", description="idk", category=d), Drink(korean_name="아이스 카라멜 마키아또", english_name="Iced Caramel Macchiato", description="idk", category=d), Drink(korean_name="카라멜 마키아또", english_name="Caramel Macchiato", description="idk", category=d), Drink(korean_name="아이스 카푸치노", english_name="Iced Cappuccino", description="idk", category=d), Drink(korean_name="카푸치노", english_name="Cappuccino", description="idk", category=d), Drink(korean_name="라벤더 카페 브레베", english_name="Lavender Cafe Breve", description="idk", category=d), Drink(korean_name="럼 샷 코르타도", english_name="Rum Shot Cortado", description="idk", category=d), Drink(korean_name="바닐라 빈 라떼", english_name="Vanilla Bean Latte", description="idk", category=d), Drink(korean_name="블론드 에스프레소 라떼", english_name="Blonde Espresso Latte", description="idk", category=d), Drink(korean_name="사케라또 비안코 오버 아이스", english_name="Shakerato Bianco Over Ice", description="idk", category=d), Drink(korean_name="스타벅스 돌체 라떼", english_name="Starbucks Dolce Latte", description="idk", category=d), Drink(korean_name="아이스 라벤더 카페 브레베", english_name="Iced Lavender Cafe Breve", description="idk", category=d), Drink(korean_name="아이스 바닐라 빈 라떼", english_name="Iced Vanilla Bean Latte", description="idk", category=d), Drink(korean_name="아이스 블론드 에스프레소 라떼", english_name="Iced Blonde Espresso Latte", description="idk", category=d), Drink(korean_name="아이스 스타벅스 돌체 라떼", english_name="Iced Starbucks Dolce Latte", description="idk", category=d), Drink(korean_name="아이스 카페 라떼", english_name="Iced Caffe Latte", description="idk", category=d), Drink(korean_name="카페 라떼", english_name="Caffe Latte", description="idk", category=d),Drink(korean_name="아이스 카페 모카", english_name="Iced Caffe Mocha", description="idk", category=d), Drink(korean_name="아이스 화이트 초콜릿 모카", english_name="Iced White Chocolate Mocha", description="idk", category=d), Drink(korean_name="카페 모카", english_name="Caffe Mocha", description="idk", category=d), Drink(korean_name="화이트 초콜릿 모카", english_name="White Chocolate Mocha", description="idk", category=d),Drink(korean_name="바닐라 플랫 화이트", english_name="Vanilla Flat White", description="idk", category=d),Drink(korean_name="바닐라 스타벅스 더블 샷", english_name="Vanilla Starbucks Double Shot", description="idk", category=d),Drink(korean_name="블론드 바닐라 더블 샷 마키아또", english_name="Blonde Vanilla Double Shot Macchiato", description="idk", category=d),Drink(korean_name="사케라또 아포카토", english_name="Shakerato Affogato", description="idk", category=d),Drink(korean_name="스파클링 시트러스 에스프레소", english_name="Sparkling Citrus Espresso", description="idk", category=d),Drink(korean_name="아이스 블론드 바닐라 더블 샷 마키아또", english_name="Iced Blonde Vanilla Double Shot Macchiato", description="idk", category=d),Drink(korean_name="에스프레소", english_name="Espresso", description="idk", category=d),Drink(korean_name="커피 스타벅스 더블 샷", english_name="BCoffee Starbucks Double Shot", description="idk", category=d),Drink(korean_name="클래식 아포가토", english_name="Classic Affogato", description="idk", category=d),Drink(korean_name="헤이즐넛 스타벅스 더블 샷", english_name="Hazelnut Starbucks Double Shot", description="idk", category=d)])
e = Category.objects.get(id=4)
Drink.objects.bulk_create([Drink(korean_name="더블 에스프레소 칩 프라푸치노", english_name="Double Espresso Chip Frappuccino", description="idk", category=e),Drink(korean_name="모카 프라푸치노", english_name="Mocha Frappuccino", description="idk", category=e),Drink(korean_name="에스프레소 프라푸치노", english_name="Espresso Frappuccino", description="idk", category=e),Drink(korean_name="자바 칩 프라푸치노", english_name="Java Chip Frappuccino", description="idk", category=e),Drink(korean_name="카라멜 프라푸치노", english_name="Caramel Frappuccino", description="idk", category=e),Drink(korean_name="화이트 초콜릿 모카 프라푸치노", english_name="White Chocolate Mocha Frappuccino", description="idk", category=e),Drink(korean_name="바닐라 크림 프라푸치노", english_name="Vanilla Cream Frappuccino", description="idk", category=e),Drink(korean_name="봄 딸기 그린 크림 프라푸치노", english_name="Spring Strawberry Green Cream Frappuccino", description="idk", category=e),Drink(korean_name="제주 까망 크림 프라푸치노", english_name="Jeju Black Sesame Cream Frappuccino", description="idk", category=e),Drink(korean_name="제주 쑥떡 크림 프라푸치노", english_name="Jeju Mugwort Cream Frappuccino", description="idk", category=e),Drink(korean_name="제주 유기농 말차로 만든 크림 프라푸치노", english_name="Malcha Cream Frappuccino from Jeju", description="idk", category=e),Drink(korean_name="초콜릿 크림 칩 프라푸치노", english_name="Chocolate Cream Chip Frappuccino", description="idk", category=e),Drink(korean_name="화이트 타이거 프라푸치노", english_name="White Tiger Frappuccino", description="idk", category=e)])
f = Category.objects.get(id=5)
Drink.objects.bulk_create([Drink(korean_name="망고 패션 프루트 블레디드",english_name="Mango Passion Fruit Blended", description="idk", category=f), Drink(korean_name="딸기 딜라이트 요거트 블렌디드", english_name="Strawberry Delight Yogurt Blended",description="idk",category=f),Drink(korean_name="망고 바나나 블렌디드",english_name="Mango Banana Blended
",description="idk",category=f),Drink(korean_name="민트 초콜릿 칩 블렌디드",english_name="Mint Chocolate Chip Blended", description="idk", category=f),Drink(korean_name="피치 & 레몬 블렌디드", english_name="Peach & Lemon Blended", description="idk", category=f)])
g = Category.objects.get(id=6)
Drink.objects.bulk_create([Drink(korean_name="블랙 티 레모네이트 피지오",english_name="Black Tea Fizzio", description="idk", category=g),Drink(korean_name="쿨 라임 피지오",english_name="Cool Lime Fizzio", description="idk", category=g),Drink(korean_name="패션 탱고 피지오",english_name="Passion Tango Fizzio", description="idk", category=g)])
h = Category.objects.get(id=7)
Drink.objects.bulk_create([Drink(korean_name="라임 패션 티",english_name="Lime Passion Tea", description="idk", category=h)])
i = Category.objects.get(id=8)
Drink.objects.bulk_create([Drink(korean_name="시그니처 핫 초콜릿",english_name="Signature Hot Chocolate", description="idk", category=i)])
j = Category.objects.get(id=9)
Drink.objects.bulk_create([Drink(korean_name="기운내라임 190ML",english_name="Lime & Lemon", description="idk", category=j)])
아.....3개씩만 할걸....
cvs로 해결하는 방법도 있는데, 맥에서는 만들어본적이 없어서 그냥 했더니 이 지경이 발생했다 ㅜㅜㅜ 똑똑하게 살자...
이미지는 실제 url정보를 받아오기는 지금은 힘드니..임의로 한번 만들어보자. 가상의 url이다(아마도?).
아래처럼 5개만 우선 작성해주자. 바닐라 크림 콜드브루는 2장으로 가정해줬다.
"https://counting_star.image/nitrovanilla/1.jpg"
"https://counting_star.image/nitrocold/1.jpg"
"https://counting_star.image/dolcecold/1.jpg"
"https://counting_star.image/vanillacream/1.jpg"
"https://counting_star.image/vanillacream/2.jpg"
코드를 적어주자.
v = Drink.objects.get(id=1)
c = Drink.objects.get(id=2)
d = Drink.objects.get(id=3)
r = Drink.objects.get(id=4)
Images.objects.bulk_create([Images(image_url="https://counting_star.image/nitrovanilla/1.jpg", drink=v),Images(image_url="https://counting_star.image/nitrocold/1.jpg", drink=c),Images(image_url="https://counting_star.image/dolcecold/1.jpg", drink=d),Images(image_url="https://counting_star.image/vanillacream/1.jpg", drink=r),Images(image_url="https://counting_star.image/vanillacream/2.jpg", drink=r)])
역참조를 진행할 때 _set
을 사용한다. 장고는 Query_set 의 형태로 호출되면서 리스트의 형태를 가지고 있기 때문에 리스트와 사용법이 비슷하다. Menu -> Category -> Drink -> Images 의 순서로 역참조를 따라가보자.
아래를 참고하자.
a = Menu.objects.get(id=1) # pk값이 1인 메뉴를 a에 담아줬다.
b = a.category_set.all()[0] # Menu(id=1) 을 참조하고 있는 Category로 역참조를 들어간 후 b에 담아줬다
c = b.drink_set.all()[0] # Menu(id=1)을 참조하고 있는 Category의 첫 번째 음료를 역참조로 들어간 후 c에 담아줬다.
d = c.images_set.all()[0] # Menu(i=1)을 참조하고 있는 Category의 첫 번째 음료를 참조하고 있는 Imaged의 첫 번째 row를 역참조로 들어갔다.
d.images_url
>>>
'https://counting_star.image/nitrovanilla/1.jpg'
정상적으로 출력되는 것을 확인했다. 여기서 주의할 점은 a. / b. 등 뒤에 붙는 category, drink, images는 소문자로 표기된 클래스 명이다. Database의 Table 명이 아닌 것을 명심하자.
클래스의 이름은 카멜케이스+단수로 작성하는 것이 국룰인데, 사진은 클래스명을 Images 로 잘못지어졌다..
수정해야하지만 지금은 학습을 위해 수행하는 것이니, 나중에 꼭 기억해서 실수를 하지 말자. 물론 조금 더 다듬고 수정을 진행할 예정이다.
알러지의 데이터를 입력해주자.
Allergy.objects.bulk_create([Allergy(name="우유"),Allergy(name="대두"),
Allergy(name="밀"),Allergy(name="땅콩"),Allergy(name="난류"),Allergy(name="오징어")])
중간테이블인 AllergyOfDrink 도 입력해주자.
a = Allergy.objects.get(id=1)
a1 = Drink.objects.get(id=1)
a2 = Drink.objects.get(id=3)
a3 = Drink.objects.get(id=4)
a4 = Drink.objects.get(id=5)
AllergyOfDrink.objects.bulk_create([AllergyOfDrink(allergy=a, drink=a1),AllergyOfDrink(allergy=a, drink=a2),AllergyOfDrink(allergy=a, drink=a3),AllergyOfDrink(allergy=a, drink=a4)])
#우유와 대두를 동시에 지니고 있는 콜드 브루 몰트를 시험해보자.
a5 = Drink.objects.get(id=9)
AllergyOfDrink.objects.create(allergy=a,drink=a5)
b = Allergy.objects.get(id=2)
AllergyOfDrink.objects.create(allergy=b,drink=a5)
잘 들어간 모습을 확인했다.
슬슬 데이터를 넣는 작업은 마무리가 되가는 것 같다.
사이즈도 넣어주자. 사이즈는 short, tall, grande, venti, trenta 5가지고 각 용량은 236, 354, 473, 591, 917 ml 이다.
온스는...8, 12, 16, 19, 31 온스다. 역시나 버크로 진행하자. 편하다 :)
Size.objects.bulk_create([Size(name="Short",size_ml="236",size_fluid_ounce="8"),Size(name="Tall",size_ml="354",size_fluid_ounce="12"),Size(name="Grande",size_ml="473",size_fluid_ounce="16"),Size(name="Venti",size_ml="591",size_fluid_ounce="19"),Size(name="Trenta",size_ml="917",size_fluid_ounce="31")])
마지막으로 영양정보를 작성해보자. 5개만 기입해보자..흑흑
Nutrition.objects.bulk_create([Nutrition(drink=Drink.objects.get(id=1), size=Size.objects.get(id=2),one_serving_kca=80,sugars_g=10,protein_g=1,sodium_mg=40,saturated_fat_g=2,caffeine_mg=232),Nutrition(drink=Drink.objects.get(id=2), size=Size.objects.get(id=2),one_serving_kca=5,sugars_g=0,protein_g=0,sodium_mg=5,saturated_fat_g=0,caffeine_mg=245),Nutrition(drink=Drink.objects.get(id=3), size=Size.objects.get(id=2),one_serving_kca=265,sugars_g=29,protein_g=8,sodium_mg=130,saturated_fat_g=9,caffeine_mg=150),Nutrition(drink=Drink.objects.get(id=4), size=Size.objects.get(id=2),one_serving_kca=125,sugars_g=11,protein_g=3,sodium_mg=58,saturated_fat_g=6,caffeine_mg=150),Nutrition(drink=Drink.objects.get(id=5), size=Size.objects.get(id=2),one_serving_kca=150,sugars_g=17,protein_g=2,sodium_mg=15,saturated_fat_g=6,caffeine_mg=190)])
흑흑..csv를 이용한 방법을 이제부터 공부해야겠다.
git...git이 문제가 되었다.. 커밋시점이 달라서 풀리퀘가 발생하지 않는다 돌아버리겠다..리베이스로 하면 해결이 될까 했는데...이것도 안된다...
다시..해야겠다....
다시 하려고 했는데, git push origin +branch로 강제 진행했더니 됐다.ㅎㅎㅎㅎ 이러면 안되는데 우선 그냥 진행했다. git 사용법에 대해서 더 공부해야겠다.
Author And Source
이 문제에 관하여(장고 - 별다방 저장소), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@holyja/장고-별다방-저장소저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)