[Django]ORM QuerySet method
Model method(또는 QuerySet method)를 통하여 Django에 내장된 데이터 관리 기능을 사용할 수 있습니다.
우선, models.py의 코드는 다음과 같습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | from tkinter import CASCADE from unicodedata import category from django.db import models # Create your models here. class Menu(models.Model): name = models.CharField(max_length=45) class Meta: #모델에 대한 다양한 사항 정의 db_table = 'menu' # 테이블을 식별하는데 사용하는 이름 설정(db상 이름 menus) class Categories(models.Model): name = models.CharField(max_length=45) menu = models.ForeignKey('Menu', on_delete=models.CASCADE) # 1:N에서 N쪽이 관계(FK)선언 # CASCADE: 1쪽이 삭제됐을때 모든 N쪽 데이터 삭제 class Meta: db_table = 'categories' class Images(models.Model): image_url = models.CharField(max_length=300) drink = models.ForeignKey('Drinks',on_delete=models.CASCADE) class Meta: db_table = 'images' class Drinks(models.Model): korean_name = models.CharField(max_length=45) english_name = models.CharField(max_length=45) description = models.TextField(max_length=100) category = models.ForeignKey('Categories', on_delete=models.CASCADE) class Meta: db_table = 'drinks' class Allergy_drink(models.Model): #drinks와 allergy 의 중간테이블 allergy = models.ForeignKey('Allergy', on_delete=models.CASCADE) drink = models.ForeignKey('Drinks', on_delete=models.CASCADE) class Meta: db_table = 'allergy_drink' class Allergy(models.Model): name = models.CharField(max_length=45) drinks = models.ManyToManyField(Drinks, through='Allergy_drink') #through에 중간테이블명 넣어줌 class Meta: db_table = 'allergy' class Nutritions(models.Model): one_serving_kcal = models.DecimalField(max_digits=10, decimal_places=5) sodium_mg = models.DecimalField(max_digits=10, decimal_places=5) saturated_fat_g = models.DecimalField(max_digits=10, decimal_places=5) sugars_g = models.DecimalField(max_digits=10, decimal_places=5) protein_g = models.DecimalField(max_digits=10, decimal_places=5) drink = models.ForeignKey('Drinks', on_delete=models.CASCADE ) size = models.ForeignKey('Sizes', on_delete=models.CASCADE) class Meta: db_table = 'nutritions' class Sizes(models.Model): name = models.CharField(max_length=45) size_mi = models.CharField(max_length=45) size_fluid_ounce = models.CharField(max_length=45) class Meta: db_table = 'sizes' # # categories(다) - (일)menu : one-to-many : Menu 메뉴에 음료/푸드/상품 등 카테고리 # # drinks(다) - (일)categories : one-to-many # # images (다) - drinks(일) : one-to-many # # nutritions(다) - drinks(일) : one-to-many # # nutritions(다) - sizes(일) : one-to-many # drinks(다) - (다) allergy : many-to-many / allergy_drink 중간테이블 # NULL은 포인터가 가져올 값이 없는 상태 # 중간테이블 직접 정의 through model 데 |
menu변수에 객체 담아줍니다
menu = Menu.objects.get(id=2) menu <Menu: Menu object (2)>
_set 을 이용해 categories를 나타내는 매니저를 설정하고, get으로 역참조 객체(categories) 가져옵니다.
- menu.categories_set.get(id=4) # 역참조시 _set 사용
- <Categories: Categories object (4)>
- menu.categories_set.get(id=4).name '브레드'
filter로 역참조 객체를 가져옵니다.
- menu.categories_set.filter(id=4)
- <QuerySet [<Categories: Categories object (4)>]>
- menu.categories_set.filter(id=4).name
- Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'QuerySet' object has no attribute 'name'
filter는 객체가 아닌 Queryset을 반환하기에 .name을 했을 시 값이 나오지 않는 모습입니다
따라서 [0]을 통해서 Queryset안의 객체를 꺼내주면 .name으로 카테고리의 이름을 확인할 수 있습니다.
- menu.categories_set.filter(id=4)[0].name
- '브레드'
- category = Categories.objects.get(id=1)
- category.menu
- <Menu: Menu object (1)>
- category.menu.name
- '음료'
drink에 get으로 객체를 담고 .allergy를 찍으니 Drinks에 allergy란 속성이 없다고 합니다.
- drink = Drinks.objects.get(id=4)
- drink.allergy
- Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Drinks' object has no attribute 'allergy'
- drink.allergy_set.all()
- <QuerySet [<Allergy: Allergy object (2)>, <Allergy: Allergy object (6)>]> drink.allergy_set.get(id=2).name
- '우유'
- for i in drink.allergy_set.all(): print(i.name)
- ...
- 우유
- 토마토
- allergy = Allergy.objects.get(id=2)
- allergy.drinks_set.get(id=1)
- Traceback (most recent call last): File "<console>", line 1, in <module> AttributeError: 'Allergy' object has no attribute 'drinks_set'
allergy.drinks <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x7ffab86eafd0>
drink.allergy_set <django.db.models.fields.related_descriptors.create_forward_many_to_many_manager.<locals>.ManyRelatedManager object at 0x7ffab86eacd0>
추가.
1. exclude(), values(), values_list()를 활용해 DB로부터 READ를 해보았습니다
value_list는 값만 있는 리스트가 반환되는 반면, values는 {'name':'값"} 의 형식으로 딕셔너리가 반환됩니다.
- Allergy.objects.exclude(id=1).values_list('name')
- <QuerySet [('우유',), ('난류',), ('밀',), ('아황산류',), ('토마토',)]>
- Allergy.objects.exclude(id=1).values('name')
- <QuerySet [{'name': '우유'}, {'name': '난류'}, {'name': '밀'}, {'name': '아황산류'}, {'name': '토마토'}]>
- Categories.objects.filter(
menu__name="음료"
)
- <QuerySet [<Categories: Categories object (1)>, <Categories: Categories object (2)>]>