파이썬 쉘 - 데이터 생성 및 쿼리 작성

devmin·2020년 2월 20일
0
  • 아직 작성중

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()
...

SubCategory 에서 음료2의 SubCategory 이름 찾기

음료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}]>

profile
개발자가 되어가는 중

0개의 댓글