본문 바로가기

레퍼런스/장고 튜토리얼

장고(Django) API와 놀기.

이제, 상호작용 가능한 파이썬 쉘에 들어가서 장고의 API와 함께 놀아봅시다. 파이썬 쉘을 불러오기 위해선 아래 커맨드를 써야합니다 :

 

$ python3 manage.py shell

 

"python3"를 사용하는 대신에 manage.py를 입력하는 이유는 DJANGO_SETTINGS_MODULE 환경변수를 설정하기 위해서입니다. 장고의 파이썬 import path를 여러분의 chem/settings.py 파일에 알려주는 셈이죠.

 

데이터베이스 API를 한번 탐색해 보도록 합시다 :

 

 

>>> from polls.models import Choice, Question  # Import the model classes we just wrote.

# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>

# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())

# Save the object into the database. You have to call save() explicitly.
>>> q.save()

# Now it has an ID.
>>> q.id
1

# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)

# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()

# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>

 

마지막 문장에서 출력된 <Question: Question object (1)>은 오브젝트를 대표해주지 않습니다. 이걸 Question 모델(polls/models.py 파일) 안에 있는 QuestionChoice __str__() 메소드를 수정해서 바꿔보겠습니다.

 

# polls/models.py

from django.db import models

class Question(models.Model):
    # ...
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

 

__str___() 메소드를 추가하는 것은 여러분 자신의 편의 뿐 아니라 상호 프롬프트와 교류할 때 장고가 자동으로 생성하는 admin에서도 오브젝트의 대표성을 나타내는  데 도움이 됩니다.

 

이 모델에 커스텀 메소드를 또 추가해보죠 :

 

# polls/models.py

import datetime

from django.db import models
from django.utils import timezone

class Question(models.Model):
	# ...
    def was_published_recently(self):
    	return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

 

import datetimefrom django.utils import timezone을 추가해야 합니다. 파이썬의 datetime 모듈과 장고의 타임존과 연관된 유틸리티인 django.utils.timezone을 각기 참조합니다. 파이썬의 time zone과 익숙하지 않다면 여기를 참조하세요.

 

다시 python3 manage.py shell을 시작해서 파이썬 상호 프롬프트를 켭니다 :

 

>>> from polls.models import Choice, Question

# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>

# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>

# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>

# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Question matching query does not exist.

# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>

# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True

# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)

# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>

# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)

# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>

# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3

# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>

# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()

 

모델 관계에 대해서 더 많은 정보를 원한다면, 연관 오브젝트 접근에 대해 읽어보세요.

Field lookups, Database API reference도 확인해보세요.