www.youtube.com/watch?v=PD3YnPSHC-c&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=7
이 포스팅은 다음과 같은 youtube 영상을 따라하면서 배운 내용과 학습 내용을 담은 것이다:
- Dennis Ivy - Model Queries | Getting Started | Django Framework (3.0) Crash Course Tutorials (pt 7)
현재 Django Version 3.1.2 를 쓰고 있다. Django는 파이썬을 쓰는 오픈소스 웹 프레임워크이다. 웹사이트 만들때 주로 쓰며, 간단한 것이 큰 특징이다.
1. Django ORM and QuerySet
우선, ORM이 무엇인지 알아보자. ORM은 Object Modeling 과 Relational Modeling을 일컫는 말이다. 즉, Object의 관계를 Modeling 해주는 시스템이다.
QuerySet의 경우, Model로부터 전달 받은 Object의 목록이다. QuerySet은 Database를 읽고, 이를 추가하거나 정렬하는 등의 작업들을 할 수 있다.
crm1 폴더 안에서 다음과 같은 작업을 해준다.
python manage.py shell
>>>
해당 코드를 입력하게 되면 Interative Console이라고 Django의 QuerySet을 다룰 수 있는 IDE가 나온다고 생각하면 된다.
>>> from accounts.models import *
시작하기 전에 이와 같은 코드를 입력해주어야 shell에서 models의 값들을 입력 받을 수 있다.
이번에는 다음과 같은 QuerySet method들을 다루어보도록 하겠다 (all(), first(), last(), filter(), )
2. all(), first(), last()
1. all()
>>> customers = Customer.objects.all()
>>> customers
<Queryset [<Customer : customer1_name>, <Customer : customer2_name>]>
위의 코드는 customers라는 변수를 만들어, Customer Class를 불러온다. customer class에서 모든 object들을 불러오고 싶을때 .objects.all()을 사용한다. 이를 입력할 경우 다음과 같은 dictionary 형식의 값을 불러온다. 이를 통해 Customer에 있는 모든 objects들을 customers라는 variable에 저장하고 불러오는 것을 할 수 있다.
2. first(), last()
>>> firstcustomer = Customer.objects.first()
>>> lastcustomer = Customer.objects.last()
>>> firstcustomer
<Customer : customer1_name>
>>> lastcustomer
<Customer : customer2_name>
first() 와 last()는 해당 Class의 첫번째와 마지막 object를 가져오고 싶을때 사용할 수 있다. 실행할 경우 위와 같은 결과를 보여준다.
3. exclude()
>>> Customer.objects.exclude(name="customer2_name")
<QuerySet [<Customer: customer1_name>]>
exclude()의 경우, 괄호 안에 들어가는 값들을 제외한 Query들을 모아서 새로운 QuerySet을 출력한다.'
4. get(), get_or_create()
1. get()
>>> customerByName = Customer.objects.get(name="customer1_name")
>>> customerByName
<Customer: customer1_name>
>>> customerById = Customer.objects.get(id=1)
>>> customerById
<Customer: customer1_name>
반대로 원하는 값들을 포함한 Query들을 출력하는 방법은 get()을 사용하는 있다. 원하는 name을 입력해도 되고, id에 따라 원하는 값을 찾아낼 수도 있다.
만약 get()이 입력받은 변수에 따른 값을 찾아내지 못한다면, 다음과 같이 출력한다
>>> customer = Customer.objects.get(id=1234)
...
Model.DoesNotExist: Customer matching query does not exist
만약 이렇게 존재하지 않는 object가 있고, 이러한 object가 Class 안에 있기를 바란다면 get_or_create()라는 method를 사용할 수 있다.
2. get_or_create()
>>> obj, create = Customer.objects.get_or_create(name="customer3_name")
>>> Customer.objects.all()
<QuerySet [<Customer: customer1_name>, <Customer: customer2_name>, <Customer: customer3_name>]>
customer3_name이라는 새로운 이름을 가진 Customer을 get_or_create()을 통해 QuerySet에 존재하는지 확인해주고 없으면 만들어주는 것을 볼 수 있다. (create()도 비슷한 원리다)
※ 주의할 점은, get_or_creat()이나 create()을 사용할때, 중복되는 field 이름을 가지지 않게끔 주의해야한다. 안그러면 IntegrityError를 불러 일으킨다
5. _set.all()
>>> customer = Customer.objects.get(id=1)
# 꼭 get(id=1)이 아니어도 된다. 단지 예시로 보여주기 위함으로, customer 한명을 특정시킬 수 있으면 된다.
>>> customer.order_set.all()
<QuerySet [<Order: Order object1>]>
특정 customer이 시킨 모든 주문을 확인하고 싶다면 order_set.all()을 사용한다. 만약 주문이 아닌 다른 것을 확인하고 싶다면 example_set.all()을 사용하면 된다. (Dennis Ivy에서 customer에 해당되는 것은 현재 Order 밖에 없기 때문에 order_set.all()으로 설명한다.)
6. filter()
1. One to One Field
>>> products = Product.objects.filter(category="Out Door")
>>> products
<QuerySet [<Product: Barbeque Grill>, <Product: Ball>]>
filter를 통해 특정 category나 object를 가진 product들을 모두 filter해낼 수 있다.
2. ManyToMany Field
>>> productsFiltered = Product.objects.filter(tags__name="Sports")
>>> productsFiltered
<QuerySet [<Product: Ball>]>
앞서 포스팅들에서 만들었던 class들을 보아라:
...
class Product(models.Model):
CATEGORY = (
('Indoor', 'Indoor'),
('Out Door', 'Out Door'),
)
name = models.CharField(max_length=200, null=True)
price = models.FloatField(null=True)
category = models.CharField(max_length=200, null=True, choices=CATEGORY)
description = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
tags = models.ManyToManyField(Tag)
def __str__(self):
return self.name
...
class라는 product 안에 tags라는 object가 있다. 하지만 tags는 결국 Tag라는 class에서 불러온 것이므로, 결국 ManyToMany Relationship에 해당된다. 위에 있는 category의 경우는 원래 Products Class 안에 내장되어 있는 objects이므로 One To One Relationship이 된다.
이렇게 Many To Many Relationship 에서 다른 class에 있는 값을 불러오기 위해서는 '__' ('_' 두번)을 사용해야 한다. 따라서 tags__name="Sports"의 방식으로 Tag Class의 이름을 불러온다
7. order_by
>>> leastToGreatest = Product.objects.all().order_by('id')
>>> greatestToLeast = Product.objects.all().order_by('-id')
>>> leastToGreatest
<QuerySet [<Product: Barbeque Grill>, <Product: Dishes>, <Product: Ball>]>
>>> greatestToLeast
<QuerySet [<Product: Ball>, <Product: Dishes>, <Product: Barbeque Grill>]>
order_by() 어떤 방식으로 QuerySet을 나열할건지 정해준다. 'id'의 경우 id를 작은 순서부터 큰 순서로 오름차순으로 정렬한다. '-id'의 경우, 내림차순으로 정렬하는 방식이다. 이렇게 내림차순으로 정렬하려면 앞에 '-'를 붙이면 된다