Django - 3. Tutorial 따라하기 3
에서
$ python manage.py migrate
을 통해
데이터베이스 테이블을 만들었습니다.
polls/models.py
파일을 수정하여
Question 과 Choice 라는 두개의 모델을 만들었습니다.
그리고 현재 프로젝트에게 polls 앱이 설치되어 있다는 것을 알리기 위해mysite/mysite/settings.py 파일을 편집하여 INSTALLED_APPS 설정에
'polls.apps.PollsConfig'를 추가했습니다.
그리고 $ python manage.py makemigrations polls
를 통해 makemigrations 을 실행시킴으로서, 모델을 변경시킨 사실과 이 변경사항을 migration으로 저장시키고 싶다는 것을 Django에게 알려줬습니다.
그리고 마지막으로 $ python manage.py migrate
을 통해 아직 적용되지 않은 migration을 모두 수집해 테이블로 만들었습니다.
이제, API를 다루는 방법에 대해 포스팅하겠습니다.
$ python manage.py shell
을 통해 python shell을 실행합니다.
$ python
이 아니라 굳이 이렇게 실행하는 이유는
manage.py 에 설정된 DJANGO_SETTINGS_MODULE 환경변수 때문입니다.
이 환경변수는 mysite/settings.py 파일에 대한 Python 임포트 경로를
Django에게 제공하여 대화식 Python 쉘에서 Django가 접근할 수 있는 Python 모듈 경로를 그대로 사용 할 수 있습니다.
즉, Django에서 동작하는 모든 명령을 대화식 Python 쉘에서 그대로 시험해 볼 수 있습니다.
쉘에 진입한 후, 데이터베이스 API를 살펴볼 수 있습니다.
>>> from polls.models import Choice, Question
# 전에 작성한 Choice, Question 모델을 import합니다.
# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>
# 새 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())
# 데이터베이스에 object를 저장해줍니다.
>>> q.save()
# 이제 id를 갖습니다.
>>> q.id
1
# Python attribute를 통해 모델의 field value에 접근할 수 있습니다.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# value를 바꿀 수 있으며 save()로 저장해야 합니다.
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all()을 통해 데이터베이스 내에 있는 모든 question들을 볼 수 있습니다.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
polls/models.py 파일을 수정하여, __str__()
메소드를 Question과 Choice에 추가해 보겠습니다.
#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__()
메소드를 추가하는것은 객체의 표현을 대화식 프롬프트에서 편하게 보려는 이유 말고도, Django 가 자동으로 생성하는 관리 사이트 에서도 객체의 표현이 사용되기 때문입니다.
모델에 커스텀 메소드 또한 추가해보겠습니다.
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 datetime은 Python의 표준 모듈인 datetime 모듈을,
from django.utils import timezone은 Django의 시간대 관련 유틸리티인 django.utils.timezone을 참조하기 위해 추가한 것입니다.
이 내용은 나중에 자세히 알아보겠습니다.
변경된 사항을 저장하고, python 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()