당신은 멋쟁이, 우리는 장고쟁이~

0%

Writing your first Django app, part2 - 6편

API 가지고 놀기 - 3편


지난 시간에 이어서, API 실험을 이어서 합니다.


[1] 부터 [6] 까지는, 지난 포스팅에서 진행한 내용 입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
In [1]: Question.objects.all()                                                                                                                                            
Out[1]: <QuerySet [<Question: What's up?>]>

In [2]: Question.objects.filter(id=1)
Out[2]: <QuerySet [<Question: What's up?>]>

In [3]: Question.objects.filter(question_text__startswith='What')
Out[3]: <QuerySet [<Question: What's up?>]>

In [4]: from django.utils import timezone

In [5]: current_year = timezone.now().year

In [6]: Question.objects.get(pub_date__year=current_year)
Out[6]: <Question: What's up?>


없는 데이터 요청하기


1
2
3
4
5
6
7
8
9
# id가 2번인 값을 조회했습니다. 
# Question은 한개밖에 없으니까, 2번은 존재하지 않습니다.
# 따라서 아래와 같은 에러가 표시됩니다.

In [7]: Question.objects.get(id=2)
---------------------------------------------------------------------------
DoesNotExist Traceback (most recent call last)
<ipython-input-7-75091ca84516> in <module>
----> 1 Question.objects.get(id=2)


pk로 데이터 찾기



primary key 로 데이터를 조회하는것은 일반적인 일입니다. 따라서, Django 는 primary-key 단축키를 제공합니다. 아래 코드는 Question.objects.get(id=1) 과 동일합니다.


1
2
3
4
5
In [8]: Question.objects.get(pk=1)                                                                                                                                        
Out[8]: <Question: What's up?>

In [9]: Question.objects.get(id=1)
Out[9]: <Question: What's up?>


Custom 메서드 동작 확인



Question 에 was_plubished_recently() 라는 메서드를 추가해 줬었습니다.

이게 잘 작동하는지 확인 해 봅니다. True 를 반환 한다면, 잘 작동하는것으로 볼수 있습니다.


1
2
3
4
In [12]: q = Question.objects.get(pk=1)                                                                                                                                   

In [13]: q.was_published_recently()
Out[13]: True


Choice 로 조회하기



DATABASE API를 통해서, 하나의 Question 에 여러개의 Choice 를 등록할수 있습니다.

몇개의 Choice 를 하나의 Question 에 등록하는 과정을 진행 합니다.


1
2
3
4
5
6
7
# q에 pk값이 1인 Question 을 할당합니다 
In [1]: q = Question.objects.get(pk=1)

# q.choice_set.all() 을 하면, 해당 Question 에 달려있는 Choice 들이 검색됩니다.
# 비어있는 쿼리셋이 출력됩니다. 아직, 해당 Question 에는 어떠한 Choice 도 등록한적 없기 때문입니다.
In [2]: q.choice_set.all()
Out[2]: <QuerySet []>


Question 과 Choice 는 ForeignKey 로 연결되어 있습니다.

One-To-Many 관계로 이어져 있습니다.

하나의 Question - 다수의 Choice 관계 입니다.

하나의 Question 을 q 에 할당했고,

q 에 달려있는 Choice 는, q.choice_set.all() 로 검색이 가능합니다.


Choice 등록하기



What’s up Question 에 3개의 Choice 를 등록해 봅니다


1
2
3
4
5
6
7
8
9
10
In [3]: q                                                                                                                                                                 
Out[3]: <Question: What's up?>

In [4]: q.choice_set.create(choice_text='Not Much', votes=0)
Out[4]: <Choice: Not Much>

In [5]: q.choice_set.create(choice_text='The Sky', votes=0)
Out[5]: <Choice: The Sky>

In [6]: c = q.choice_set.create(choice_text='Just Hacking again', votes=0)


Choice 객체에서 Question 객체 조회



q가 가진 모든 Choice 조회

q.choice_set.all()

q가 가진 모든 choice 의 갯수 조회

q.choice_set.count()



1
2
3
4
5
6
7
8
9
10
11
12
# Choice 객체 에서 관계된 Question 객체를 조회할수 있는 API 가 있습니다 
In [7]: c.question
Out[7]: <Question: What's up?>

# 반대로, Question 객체에서 Choice 객체를 조회할수 있습니다.
# What's up Question 인 q 에 달려있는 모든 Choice 를 볼수 있습니다
In [8]: q.choice_set.all()
Out[8]: <QuerySet [<Choice: Not Much>, <Choice: The Sky>, <Choice: Just Hacking again>]>

# q 에 달려있는 Choice 의 갯수를 볼수 있습니다
In [9]: q.choice_set.count()
Out[9]: 3



__의 사용


API는 자동으로 필요한만큼의 관계들을 따라갑니다. 두개의 언더스코어를 사용해서 관계를 분리 시킬수 있습니다.
몇개의 관계로 나누어도 상관 없습니다

Choice 중 question 의 pub__date가 이번년 인것을 찾으려면, 아래와 같이 써줍니다.


1
2
3
4
5
6
In [10]: from django.utils import timezone                                                                                                                                

In [11]: current_year = timezone.now().year

In [12]: Choice.objects.filter(question__pub_date__year=current_year)
Out[12]: <QuerySet [<Choice: Not Much>, <Choice: The Sky>, <Choice: Just Hacking again>]>


Choice 하나 삭제하기


delete() 함수를 사용해서, 하나의 choice 를 삭제합니다


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# q 에 달린 choice 중에 'Just hacking' 으로 시작하는것을 조회 
# c 에 할당
In [13]: c = q.choice_set.filter(choice_text__startswith='Just hacking')

In [14]: c
Out[14]: <QuerySet [<Choice: Just Hacking again>]>

# delete() 메써드를 사용해서, c 를 삭제
In [15]: c.delete()
Out[15]: (1, {'polls.Choice': 1})

# 삭제후, q에 달려 있는 choice 조회
# 3개였던것이 2개만 출력됩니다
In [16]: q.choice_set.all()
Out[16]: <QuerySet [<Choice: Not Much>, <Choice: The Sky>]>


마치며..


이 Queryset 하고 API 부분이, 매우 중요한 부분입니다.

더 많은 정보는, 장고 공식문서에 Accessing related objects 를 참조하시면 됩니다.

또한, __ 사용에 대해서는, Field lookupsDatabase API reference 를 참조하시면 됩니다.