스타벅스의 음료를 Mysql에 저장하는 과제를 wecode 백엔드 세션에서 다음의 과정을 거쳐서 같이 해보았다.
클로닝한 페이지: https://www.istarbucks.co.kr/menu/drink_list.do
설계 부분: 대분류(음료) > 소분류(카테고리) > 음료
테이블 설계시 사용하는 이름과 필드명은 장고에서 모델을 만들때도 사용한다.
테이블명과 각필드의 이름을 정할때 convention을 따르고, 신중히 정하자.
field type 선택하는 방법: validation까지 필요한 경우는 신경써서 설정해야 한다. 그렇지 않은 경우는 논리적으로 맞는 타입을 선택하면 충분하다.
(more on field type: https://docs.djangoproject.com/en/3.0/ref/models/fields/)
one-to-one(일대일) or many-to-one(다대일) : 정참조, 화살표 방향이 좌변 기준 정방향.
one-to-many(일대다) or many-to-many(다대다) : 역참조, 화살표 방향이 좌변 기준 역방향.
models.ForeignKey(to, on_delete, **options)
:
SET_NULL: Set the reference to NULL (requires the field to be nullable). For instance, when you delete a User, you might want to keep the comments he posted on blog posts, but say it was posted by an anonymous (or deleted) user. SQL equivalent: SET NULL.
models.ManyToManyField(to, **options)
:
to : 참조할 클래스의 이름
through = : many-to-many관계의 중간 테이블이 될 클래스 이름.
(More on this @https://docs.djangoproject.com/en/3.0/ref/models/fields/)
many-to-many의 클래스를 장고에게 맞기지 않고 직접 할 경우, Foreign Keys로만 이루어진 클래스를 생성.
클래스이름은 many-to-many의 관계를 가진 두개의 클래스 이름의 조합으로 만든다.
Foreign Key의 변수 이름은 _id를 쓰지않는다. DB에 저장시, 장고가 알아서 붙여준다.
한 클래스에서 아직 정의되지 않은 class의 primary key를 참조할때는, 참조하게 될 클래스 이름 앞뒤에 ' '를 넣으면 나중에 불러오게 할 수 있다.
모델 설계가 끝나면 꼭 migrations 를 잊지말자!
my_settings.py 파일을 만들어 데이터베이스를 지정한다. my_settings는 프로젝트 최상위 디렉토리에 저장하도록 하자.
settings.py를 알맞게 설정한다.
@ settings.py
...
import my_settings
...
INSTALLED_APPS = [......
......
......
'drink'
]
DATABASES = my_settings.DATABASES
pip install mysqlclient
mysql -u root -p
Enter password:
mysql> show databases;
mysql> create database starbucks character set utf8mb4 collate utf8mb4_general_ci;
mysql> use starbucks;
mysql> show tables;
+---------------------+
| Tables_in_starbucks |
+---------------------+
| allergies |
| categories |
| django_content_type |
| django_migrations |
| django_session |
| drink_allergies |
| drinks |
| sub_categories |
+---------------------+
python manage.py shell
### 카테고리/음료카테고리/음료의 레코드 추가
>>> from drink.models import *
>>> Category.objects.create(name="음료")
<Category: Category object (1)>
>>> SubCategory.objects.create(name="cold brew", category=Category.objects.get(id=1))
<SubCategory: SubCategory object (1)>
>>> Drink.objects.create(name_en="dolce cold brew", name_kr="돌체콜드브루", description="무더운 여름철,....", thumbnail="www.www.kr/jpeg", allergy="우유", serving=300.1, calories=300.4, saturated_fat=12.3, protein=30.4, sodium=3.4, sugar=100.2, caffeine=5, category=Category.objects.get(id=1), sub_category=SubCategory.objects.get(id=1))
<Drink: Drink object (1)>
>>> Drink.objects.create(name_en="cold brew", name_kr="콜드브루", description=" 무더운 여름철,....", thumbnail="www.www.kr/jpeg", allergy="우유", serving=300.1, calories=300.4, saturated_fat=12.3, protein=30.4, sodium=3.4, sugar=100.2, caffeine=5, category=Category.objects.get(id=1), sub_category=SubCategory.objects.get(id=1))
<Drink: Drink object (2)>
# 생성한 음료의 필드에 접근
>>> drink_1 = Drink.objects.get(id=1)
>>> drink_1
<Drink: Drink object (1)>
>>> drink_1.category
<Category: Category object (1)>
>>> drink_1.category_id
1
### select_related 사용하기
>>> SubCategory.objects.filter(id=drink_1.category_id)
<QuerySet [<SubCategory: SubCategory object (1)>]>
>>> SubCategory.objects.filter(id=drink_1.category_id).values
<bound method QuerySet.values of <QuerySet [<SubCategory: SubCategory object (1)>]>>
>>> SubCategory.objects.filter(id=drink_1.category_id)[0]
<SubCategory: SubCategory object (1)>
>>> SubCategory.objects.filter(id=drink_1.category_id)[0].name
'cold brew'
>>> drink_2 = Drink.objects.select_related('category').get(id=1)
>>> drink_2
<Drink: Drink object (1)>
>>> drink_2.category.name
'음료'
### prefetch_related 사용하기
>>> category = SubCategory.objects.get(id=1)
>>> category.drink_set.all()
<QuerySet [<Drink: Drink object (1)>, <Drink: Drink object (2)>]>
>>> SubCategory.objects.filter(id=1).prefetch_related("drink_set")
<QuerySet [<SubCategory: SubCategory object (1)>]>
>>> drink_3 = SubCategory.objects.filter(id=1).prefetch_related("drink_set")
>>> drink_3[0]
<SubCategory: SubCategory object (1)>
>>> drink_3[0].category
<Category: Category object (1)>
>>> drink_3[0].drink_set.filter(id=1)
<QuerySet [<Drink: Drink object (1)>]>
>>> drink_3[0].drink_set.get(id=1).name_kr
'돌체콜드브루'
.add
사용하기: drink1 = Drink.objects.get(id=2)
allergy1 = Allergy.objects.get(name='soy')
drink1.allergy.add(allergy1) #drink id=2에 allergy id=2(soy)가 더해진다
.create
사용하기:drink1.allergy.create(name='pistaccio')
>>><Allergy: Allergy object(5)> # allergies에 pistaccio가 더해진다.
결과는 DB에서 확인할 수 있다.
qs = Product.objects.all()
qs.update(is_in_stock=True)
Address.objects.filter(id=1).update(postcode_id=1, users_id=1)