python manage.py shell
에 들어와서 진행
# 전체 drink.models의 전체 모델 임포트
>>> from drink.models import *
>>> MainCategory.objects.create(name="푸드")
<MainCategory: MainCategory object (2)>
mysql> select * from main_categories;
+----+--------+
| id | name |
+----+--------+
| 1 | 음료 |
| 2 | 푸드 |
+----+--------+
# 값 생성
>>> SubCategory.objects.create(main_category_id_id=1,name="아이스크림")
<SubCategory: SubCategory object (5)>
# 있는 값 확인
>>> SubCategory.objects.values()
<QuerySet [{'id': 1, 'main_category_id_id': 1, 'name': '콜드브루'}, {'id': 2, 'main_category_id_id': 1, 'name': '브루드커피'}, {'id': 3, 'main_category_id_id': 1, 'name': '베이커리'}, {'id': 4, 'main_category_id_id': 1, 'name': '케이크'}, {'id': 5, 'main_category_id_id': 1, 'name': '아이스크림'}]>
>>> SubCategory.objects.filter(id=3)[0].main_category_id_id
mysql> select * from sub_categories;
+----+-----------------+------------------+
| id | name | main_category_id |
+----+-----------------+------------------+
| 1 | 콜드브루 | 1 |
| 2 | 브루드커피 | 1 |
| 3 | 베이커리 | 1 |
| 4 | 케이크 | 1 |
| 5 | 아이스크림 | 1 |
+----+-----------------+------------------+
사이즈 값 생성
>>> Size.objects.create(name="120g")
<Size: Size object (3)>
>>> Size.objects.values()
<QuerySet [{'id': 1, 'name': '톨'}, {'id': 2, 'name': '그란데'}, {'id': 3, 'name': '120g'}]>
mysql> select * from sizes;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 톨 |
| 2 | 그란데 |
| 3 | 120g |
+----+-----------+
영양정보 값 생성
>>> Nutrition.objects.create(onetime_jaegong = 10, pohwa_jibang = 10, danbaekzil=11, natreum=10, dang=5, caffein=245);
<Nutrition: Nutrition object (3)>
mysql> select * from nutritions;
+----+-----------------+--------------+------------+---------+------+---------+
| id | onetime_jaegong | pohwa_jibang | danbaekzil | natreum | dang | caffein |
+----+-----------------+--------------+------------+---------+------+---------+
| 1 | 75.0 | 2.0 | 1.0 | 20.0 | 10.0 | 245.0 |
| 2 | 100.0 | 1.0 | 1.0 | 10.0 | 5.0 | 245.0 |
| 3 | 10.0 | 10.0 | 11.0 | 10.0 | 5.0 | 245.0 |
| 4 | 10.0 | 110.0 | 101.0 | 110.0 | 5.0 | 45.0 |
| 5 | 110.0 | 10.0 | 91.0 | 10.0 | 50.0 | 145.0 |
| 6 | 410.0 | 140.0 | 91.0 | 109.0 | 50.0 | 45.0 |
+----+-----------------+--------------+------------+---------+------+---------+
알레르기 값 생성
>>> Nutrition.objects.create(onetime_jaegong = 410, pohwa_jibang = 140, danbaekzil=91, natreum=109, dang=50, caffein=45);
<Nutrition: Nutrition object (6)>
mysql> select * from allergies;
+----+-----------+
| id | name |
+----+-----------+
| 1 | 우유 |
| 2 | 오징어 |
| 3 | 땅콩 |
| 4 | 계란 |
| 5 | 대두 |
+----+-----------+
상품 값 생성
>>> Product.objects.create(name_kr="7레이어 가나슈 케이크", name_en="7 Layer Ganache Cake", description = "가나슈가 듬뿍", image = "???", main_category_id = 2, sub_category_id = 4, size_id=3, nutrition_id = 6)
<Product: Product object (6)>
mysql> select * from products;
+----+-------------------------------------+----------------------+---------------------------------------------------------+-------+-----------------+---------+------------------+--------------+
| id | name_kr | name_en | description | image | sub_category_id | size_id | main_category_id | nutrition_id |
+----+-------------------------------------+----------------------+---------------------------------------------------------+-------+-----------------+---------+------------------+--------------+
| 1 | 나이트로 바닐라 크림 | Nitro Vanila Cream | 부드러운 목넘김의 나이트로 커피와 등등 | ?? | 1 | NULL | 1 | 1 |
| 2 | 나이트로 쇼콜라 클라우드 | Nitro chocolat cloud | 초콜릿과 견과류의 풍미 | ?? | 1 | NULL | 1 | 1 |
| 3 | 아이스 커피 | iced coffee | 깔끔하고 상큼쓰 | ?? | 2 | NULL | 1 | 1 |
| 4 | 오늘의 커피 | brewed coffee | 신선하게 브루드 | ?? | 2 | NULL | 1 | 1 |
| 5 | 레이즌 스콘 | Raisin Scone | 건포도가 듬뿍 | ??? | 3 | 3 | 2 | 5 |
| 6 | 7레이어 가나슈 케이크 | 7 Layer Ganache Cake | 가나슈가 듬뿍 | ??? | 4 | 3 | 2 | 6 |
+----+-------------------------------------+----------------------+---------------------------------------------------------+-------+-----------------+---------+------------------+--------------+
ProductAllergy에 값 생성
(many to many로 합쳐진 테이블에 값 넣기)
# 넣고 싶은 기준 대상(음료 2)을 get을 사용해 객체로 가져옴
>>> drink2 = Product.objects.get(id=2)
# 음료2의 manytomany field인 `product_allergies`에 넣고싶은 알러지 객체들을 add로 넣는다.
>>> drink2.product_allergies.add(Allergy.objects.get(id=3),Allergy.objects.get(id=4))
mysql> select * from product_nutritions;
+----+------------+------------+
| id | allergy_id | product_id |
+----+------------+------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 3 | 1 |
| 4 | 4 | 1 |
| 5 | 3 | 2 |
| 6 | 4 | 2 |
+----+------------+------------+
shell 창에 한줄한줄 치면 저장이 안되서 값이 안바뀜. for문 처럼 값을 대입하고 바로 저장까지 할 수 있게 해야함
>>> for i in SubCategory.objects.all():
... i.main_category_id_id = 1
... i.save()
...
음료2의 서브카테고리 아이디 값과 같은 서브카테고리 객체를 뽑은 다음 name
값을 불러온다.
objects.get 은 바로 객체값을 리턴하고, all, value 등은 쿼리셋을 리턴함. 그래서 [0] 등으로 한 번 더 들어가야함
>>> drink2 = Product.objects.get(id=2)
>>> SubCategory.objects.filter(id=drink2.sub_category_id)[0].name
'콜드브루'
onetoone 이나 foreignkey 관계(정참조) 일 때 사용
django document 설명
정참조 foreign-key
관계일 때,select_related
는 쿼리를 실행하는 시점에, 관계된 객체 데이터를 추가적으로 포함해서 쿼리셋을 반환해준다. 쿼리 한줄로 따지면 복잡해보여도, 나중에 foreign-key
관계를 쓸 때 더이상 데이터베이스 쿼리를 불러오지 않아도 된다.
select_related
를 안썼을때는 Entry
객체를 불러올 때 쿼리가 한 번 발생하고, 관계된 blog 데이터를 가져올 때 쿼리가 또 발생한다.
# Hits the database.
e = Entry.objects.get(id=5)
# Hits the database again to get the related Blog object.
b = e.blog
반면에 select_related
로 첫 번째 쿼리를 할 때 blog
를 같이 불러와놓으면, 이후 이 blog
를 다시 부를 때 쿼리가 발생하지 않는다. 첫 번째 쿼리를 할 때 caching으로 쿼리를 다 저장해놔서 가능해진다.
# Hits the database.
e = Entry.objects.select_related('blog').get(id=5)
# Doesn't hit the database, because e.blog has been prepopulated
# in the previous query.
b = e.blog
원래 하고 있던 예시로 진행해보면, 음료 2의 서브카테고리명을 가져오고 싶다고 할 때, select_related
를 안쓰면 아래와 같이 작성할 수 있다.
>>> drink2 = Product.objects.get(id=2)
>>> drink2
<Product: Product object (2)>
>>> drink2.sub_category.name
'콜드브루'
select_related
를 쓰면 아래와 같이 작성할 수 있다. 위 아래 방법 둘 다 가져오는 객체와 결과물은 동일하지만, 쿼리를 불러오는 부하에 차이가 있다고 알고 있으면 된다.
>>> drink2 = Product.objects.select_related("sub_category").get(id=2)
>>> drink2
<Product: Product object (2)>
>>> drink4.sub_category.name
'콜드브루'
prefetch : 진행중인 처리와 병행하여 필요하다고 생각되는 명령 또는 데이터를 사전에 판독하는 것.
django document
지정된 각 조회에 대해 단일 배치에서 관련 개체를 자동으로 검색하는 QuerySet을 반환합니다.
이것은 select_related와 비슷한 목적을 가지고 있습니다. 둘 다 관련 객체에 액세스하여 발생하는 데이터베이스 쿼리의 유출을 막기 위해 설계되었지만 전략은 매우 다릅니다.
select_related는 SQL 조인을 생성하고 SELECT 문에 관련 개체의 필드를 포함시켜 작동합니다. 이러한 이유로 select_related는 동일한 데이터베이스 쿼리에서 관련 개체를 가져옵니다. 그러나 '다수'관계에 참여하여 발생하는 훨씬 더 큰 결과 집합을 피하기 위해 select_related는 외래 키 및 일대일 관계의 단일 값 관계로 제한됩니다.
반면에 prefetch_related는 각 관계에 대해 별도의 조회를 수행하고 Python에서 '결합'을 수행합니다. 이를 통해 select_related가 지원하는 외래 키 및 일대일 관계 외에 select_related를 사용하여 수행 할 수 없는 다 대다 및 다 대일 객체를 프리 페치 할 수 있습니다.
특정 서브카테고리의 제품들을 불러오고 싶을때, prefetch_related
안쓰고 불러오려면, 아래처럼 작성한다.
>>> sub1 = SubCategory.objects.get(id=1) [1]
>>> sub1.product_set.values() [2]
<QuerySet [{'id': 1, 'name_kr': '나이트로 바닐라 크림', 'name_en': 'Nitro Vanila Cream', 'description': '부드러운 목넘김의 나이트로 커피와 등등', 'image': '??', 'sub_category_id': 1, 'main_category_id': 1, 'size_id': None, 'nutrition_id': 1}, {'id': 2, 'name_kr': '나이트로 쇼콜라 클라우드', 'name_en': 'Nitro chocolat cloud', 'description': '초콜릿과 견과류의 풍미', 'image': '??', 'sub_category_id': 1, 'main_category_id': 1, 'size_id': None, 'nutrition_id': 1}]>
prefetch_related
>>> sub2 = SubCategory.objects.prefetch_related("product_set").get(id=2)
>>> sub2
<SubCategory: SubCategory object (2)>
>>> sub2.product_set.values()
<QuerySet [{'id': 3, 'name_kr': '아이스 커피', 'name_en': 'iced coffee', 'description': '깔끔하고 상큼쓰', 'image': '??', 'sub_category_id': 2, 'main_category_id': 1, 'size_id': None, 'nutrition_id': 1}, {'id': 4, 'name_kr': '오늘의 커피', 'name_en': 'brewed coffee', 'description': '신선하게 브루드', 'image': '??', 'sub_category_id': 2, 'main_category_id': 1, 'size_id': None, 'nutrition_id': 1}]>