갈루아의 반서재

Creating models

앞으로 여러분이 작성하게 될 어플리케이션은 특정 규약을 따르는 파이썬 패키지로 구성된다. 하나씩 살펴보자.


Projects vs. apps

먼저 app은 웹로그 시스템 등 웹 어플리케이션을 의미한다. project는 다수의 app 을 포함할 수 있으며, 하나의 app 은 다수의 프로젝트에서 활용할 수 있다. 아래에서 poll app 을 작성하는 법에 대해 알아보자.


manage.py 파일이 위치한 디렉토리에서 아래와 같이 실행하여 app을 생성한다.

$ python manage.py startapp polls

아래와 같이 디렉토리 및 파일이 생성됨

polls/
    __init__.py
    admin.py
    migrations/
        __init__.py
    models.py
    tests.py
    views.py

모델 정의하기

추가적인 메타데이터와 함께 데이터베이스의 레이아웃을 정한다.


여기서는 두 가지 모델을 생성한다. Question 과 Choice 가 그것으로 Question 에는 질문내용과 일자가, 그리고Choice 는 2가지 필드를 가지는데, 보기와 투표총수가 그것이다.


polls/models.py 을 다음과 같이 수정한다.


polls/models.py


from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')


class Choice(models.Model):
    question = models.ForeignKey(Question)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

위에서 보듯이 각각의 모델은 클래스에 의해 구현된다. 그리고 해당 모델의 데이터베이스의 필드를 의미하는 변수 클래스를 포함한다.


Activating models

앞선 작성한 간단한 코드로

• 데이터베이스 스키마를 생성할 수 있다

• Question 과 Choice 오브젝트에 접근할 수 있는 파이썬 데이터베이스-접근 API 를 생성할 수 있다.

셋팅 정보에서 설치된 앱에 polls 가 포함되도록 한다.

아래의 파일을 열어 다음과 같이 수정한다.


msite/settings.py


INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls',
)


$ python manage.py makemigrations polls


Migrations for 'polls':
  0001_initial.py:
    - Create model Question
    - Create model Choice
    - Add field question to choice



makemigrations 을 실행함으로써, models 에 변화가 생겼음을 알려주게 되는 셈이다.

원한다면 sqlmigrate 명령을 통해서 어떤 쿼리가 실행되었는지 볼 수 있다.


$ python manage.py sqlmigrate polls 0001


BEGIN;
CREATE TABLE "polls_choice" (
    "id" serial NOT NULL PRIMARY KEY,
    "choice_text" varchar(200) NOT NULL,
    "votes" integer NOT NULL
);
CREATE TABLE "polls_question" (
    "id" serial NOT NULL PRIMARY KEY,
    "question_text" varchar(200) NOT NULL,
    "pub_date" timestamp with time zone NOT NULL
);
ALTER TABLE "polls_choice" ADD COLUMN "question_id" integer NOT NULL;
ALTER TABLE "polls_choice" ALTER COLUMN "question_id" DROP DEFAULT;
CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id");
ALTER TABLE "polls_choice"
  ADD CONSTRAINT "polls_choice_question_id_246c99a640fbbd72_fk_polls_question_id"
    FOREIGN KEY ("question_id")
    REFERENCES "polls_question" ("id")
    DEFERRABLE INITIALLY DEFERRED;

COMMIT;



0001_initial.py 파일을 오픈한 모습




• 테이블 이름은 app의 이름 (polls)과 model의 이름(question, choice)의 결합된 형태로 자동 생성된다. 
• PK는 자동 생성된다(맨 하단 이미지 참조)

• 전통적으로, FK 에는 "_id" 와 같이 접미사가 붙는다.
• FK 관계는 명시적으로 표현된다. 

• sqlmigrate 명령어가 실제 마이그레이션을 수행하지 않는다. 단지 체크할 수 있도록 스크린상으로 보여줄 뿐이다.

아래 명령으로 마이그레이션을 실행하기 전에 문제가 없는지 체크할 수 있다.


(venv)root@gcloud-seoul-f461285987ddc0629f8a4ab6477642b5:~/mysite# python manage.py check
System check identified no issues (0 silenced).
(venv)root@gcloud-seoul-f461285987ddc0629f8a4ab6477642b5:~/mysite#

그러면 테이블을 생성하기 위해 migrate 명령을 실행해보자.

$ python manage.py migrate

Operations to perform:
  Synchronize unmigrated apps: staticfiles, messages
  Apply all migrations: admin, contenttypes, polls, auth, sessions
Synchronizing apps without migrations:
  Creating tables...
    Running deferred SQL...
  Installing custom SQL...
Running migrations:
  Rendering model states... DONE
  Applying <migration name>... OK

migrate 명령은 아직 적용되지 않은 모든 마이그레이션에 영향을 미친다.

아래에서 적용된 내용을 확인해보자.

db.sqlite3 파일에 접속하여 생성된 테이블(polls_questionpolls_choice)를 확인하고 컬럼명도 확인해보자.

깔끔하게 보기 위해 테이블 정보를 조회하기 전에 아래와 같이 먼저 설정한다.


sqlite> .header on
sqlite> .mode column


테이블 정보 조회

sqlite> pragma table_info("polls_question");


앞으로 더 상세하게 다뤄보겠지만, 현재까지의 내용을 정리해보면 다음과 같다.

앞서봤듯이 마이그레이션과 변경 사항 적용을 별도의 명령어로 다룬다.


• 모델 변경사항 발생 (models.py)
• python manage.py makemigrations 명령을 통해 상기 변경 사항에 대한 마이그레이션 생성 

• python manage.py migrate 을 통해 변경 사항 데이터베이스에 적용