[Django] QuerySet 정리

인간·2022년 7월 6일
0

1. 먼저 프로젝트 구조를 알아보자.

프로젝트 명 : westarbucks
작업할 app명 : products

2. products/models.py

from django.db import models


class Menu(models.Model):
    name = models.CharField(max_length=20)




    def __str__(self):  # shell에서 보이는 정보
        return f'{self.name}'

    class Meta:  
        db_table = 'menu'  # 실제 DB에 만들어지는 테이블 명




class Category(models.Model):
    name = models.CharField(max_length=20)
    menu = models.ForeignKey('Menu', on_delete=models.SET_NULL, null=True)


    def __str__(self):
        return f'{self.name}'

    class Meta:
        db_table = 'categories'




class Drink(models.Model):
    category     = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    korean_name  = models.CharField(max_length=45)
    english_name = models.CharField(max_length=45)
    description  = models.TextField()
    is_new       = models.SmallIntegerField(default=0)


    def __str__(self):
        return f'{self.korean_name}'

    class Meta:
        db_table = 'drinks'




class Image(models.Model):
    drink     = models.ForeignKey('Drink', on_delete=models.CASCADE)
    image_url = models.CharField(max_length=2000)


    def __str__(self):
        return f'{self.drink} : {self.image_url}'

    class Meta:
        db_table = 'images'




class Nutrition(models.Model):
    drink            = models.OneToOneField('Drink', on_delete=models.CASCADE)
    size             = models.CharField(max_length=20, null=True)
    size_ml          = models.IntegerField(null=True)
    size_fluid_ounce = models.IntegerField(null=True)
    one_serving_kcal = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    sodium_mg        = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    saturated_fat_g  = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    sugers_g         = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    protein_g        = models.DecimalField(max_digits=6, decimal_places=2, null=True)
    caffeine_mg      = models.DecimalField(max_digits=6, decimal_places=2, null=True)

    def __str__(self):
        return f'{self.drink} nutritions'

    class Meta:
        db_table = 'nutritions'




class Allergy(models.Model):
    name = models.CharField(max_length=45)

    def __str__(self):
        return f'{self.name}'

    class Meta:
        db_table = 'allergies'



class AllergyDrink(models.Model):
    allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE)
    drink   = models.ForeignKey('Drink', on_delete=models.CASCADE)


    def __str__(self):
        return f'{self.drink} : {self.allergy}'

    class Meta:
        db_table = 'allergy_drink'

### 3. Shell에서 데이터 조회

-Django가 import된 python shell 실행
명렁어는 manage.py가 있는 폴더에서 (중요함)

> python manage.py shell


-데이터 insert (쉘창에서 했음)


Menu.objects.create(name="음료")

Category.objects.create(name="콜드 브루", menu_id=1)

Drink.objects.create(korean_name="나이트로 바닐라 크림", category_id=1)


** 중요한건 연결된 테이블에서는 설정된 관계에 따라 순차적으로 데이터를 넣어주는게 좋다.(메뉴>카테고리>음료)


예시1.
![](https://velog.velcdn.com/images/secret0831/post/93a1b8d5-71a3-47ad-b24c-1fc943df8a5d/image.png)


- 정참조(Forward)로 연결된 데이터 조회하기.(쉘에서 진행했음)

  -- 정참조는 간편하게 점('.')으로 조회 가능하다.
  
  예시) '나이트로 바닐라 크림'라는 음료가 속한 메뉴 이름 조회하기
  
  

drink = Drink.objects.get(id=1)


drink
<Drink: 나이트로 바닐라 크림>


drink.korean_name
'나이트로 바닐라 크림'


'나이트로 바닐라 크림'이 속한 카테고리 정보 조회
drink.category
<Category: 콜드 브루>


'나이트로 바닐라 크림'이 속한 카테고리의 이름만 조회
drink.category.name
'콜드 브루'


'나이트로 바닐라 크림'이 속한 카테고리가 속한 메뉴 정보 조회
drink.category.menu
<Menu: 음료>


'나이트로 바닐라 크림'이 속한 카테고리가 속한 메뉴의 이름만 조회
drink.category.menu.name
'음료'
  • 역참조(Backward)로 연결된 데이터 조회하기
    -- 해당 객체를 참조하고 있는 다른 객체가 ForeignKey를 가지고 있거나 다대다 관계인 경우, 해당 객체 기준에서 사용하는 방법이다. (누가 날 바라보고 있는지 모르는 쪽)

    -- 즉, 부모테이블에서 자식 테이블의 특정 데이터를 조회할 때를 말한다.

Django에서 역참조를 할 수 있게 해주는 도구를 사용한다.

예시) id가 1인 메뉴를 참조하고 있는 음료 데이터 중 첫번째 데이터만 조회하기

menu = Menu.objects.get(id=1)


menu.category_set
<django.db.models.fields.related_descriptors.create_reverse_many_to_one_manager.<locals>.RelatedManager object at 0x7fde98116820>
해당 객체가 참조하는 객체명(소문자)_set은 reverse_many_to_one_manager라고 나온다., 역참조를 할 수 있게 해주는 도구이다.


id1인 메뉴를 참조하고 있는 카테고리의 모든 데이터 조회
menu.category_set.all()
<QuerySet [<Category: 콜드 브루>, <Category: 블렌디드>, <Category: 스타벅스 피지오>, <Category:(티바나)>]>


id1인 메뉴를 참조하고 있는 카테고리의 모든 데이터에서 첫번째 데이터만 조회
menu.category_set.all()[0]
<Category: 콜드 브루>


id1인 메뉴를 참조하고 있는 카테고리의 첫번째 데이터를 참조하고 있는 음료의 모든 데이터 조회
menu.category_set.all()[0].drink_set.all()
<QuerySet [<Drink: 나이트로 바닐라 크림>, <Drink: 나이트로 쇼콜라 클라우드>]>


id1인 메뉴를 참조하고 있는 카테고리의 첫번째 데이터를 참조하고 있는 음료에서 첫번째 데이터만 조회(이름만)
menu.category_set.all()[0].drink_set.all()[0].korean_name
'나이트로 바닐라 크림'
profile
잇츠미

0개의 댓글