리셋 되지 말자

[점프 투 장고] model 본문

Django

[점프 투 장고] model

kyeongjun-dev 2020. 12. 1. 16:14

장고 앱 migrate

$ python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
December 01, 2020 - 14:45:42
Django version 3.1.3, using settings 'config.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

runserver를 실행하면, 18개의 적용되지 않은 migration들이 있다고 출력된다. admin, auth, contenttypes, sessions 앱들이고, 이 앱들은 장고 설치 시 기본으로 설치되는 앱들이다. 이는 config/settings.py에서 확인할 수 있다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

언급된 앱들 이외에 messages, staticfiles도 보인다. 이 두 개는 필요없는 것으로 보일 것 같다. 앱 적용 시 migration이 필요한 경우는 데이터베이스가 필요한 경우다.

settings.py에는 데이터베이스도 정의되어 있다.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

데이터베이스 엔진은 django.db.backends.sqlite3 라고 정의되어 있다. sqlite는 파일 기반의 아주 작은 데이터베이스이다. 그리고 데이터베이스 파일은 BASE_DIR 하위에 db.sqlite3 라는 파일에 저장한다고 정의되어 있다. BASE_DIR은 프로젝트 디렉터리를 의미한다. (BASE_DIR은 현재 projects/mysite 이다.)

$ python manage.py migrate

위 명령어로 migrate를 진행한다.

 

모델 작성하기

질문  속성

 

답변 속성

 

models.py

projects/mysite/pybo 에 질문과 답변에 해당하는 모델을 models.py에 작성한다.

from django.db import models

# Create your models here.
class Question(models.Model):
    subject = models.CharField(max_length=200)
    content = models.TextField()
    create_date = models.DateTimeField()

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    content = models.TextField()
    create_date = models.DateTimeField()

Question 모델은 제목, 내용, 작성일시를 속성으로 갖는다.

제목은 최대 200자까지 가능하도록 max_length=200을 설정한다. 제목처럼 글자수의 길이가 제한된 텍스트는 CharField를 사용한다. 내용처럼 글자수를 제한할 수 없는 텍스트는 위처럼 TextField를 사용한다. 작성일시처럼 날짜와 시간에 관계된 속성은 DateTimeField를 사용한다.

Answer 모델은 질문에 대한 답변에 해당하므로 Question 모델을 속성으로 가져야 한다. 기존 모델을 속성으로 가져갈 경우 ForeignKey를 이용한다. ForeignKey는 다른 모델과의 연결을 의미한다. on_delete=models.CASCADE의 의미는 이 답변과 연결된 질문이 삭제될 경우 답변도 함께 삭제된다는 의미다.

https://docs.djangoproject.com/en/3.0/ref/models/fields/#field-types
위 URL에서 장고에서 사용하는 속성(Field)의 타입을 알 수 있다.

 

파이보 앱 등록

작성한 모델을 이용하여 테이블을 생성한다.

테이블 생성을 위해, pybo앱을 config/settings.py 파일의 INSTALLED_APPS 항목에 추가한다.

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'pybo.apps.PyboConfig'
]

추가한 pybo.apps.PyboConfig 클래스는 pybo/apps.py 파일에 있는 클래스다. 이 파일은 pybo 앱 생성시 자동으로 만들어지는 파일로 따로 만들 필요가 없다.

from django.apps import AppConfig


class PyboConfig(AppConfig):
    name = 'pybo'

(파이보 앱을 INSTALLED_APPS 항목에 추가하지 않으면 데이터베이스 관련된 작업을 할 수 없다.)

 

makemigrations

모델 생성을 위해 migrate 명령을 수행한다.

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  No migrations to apply.
  Your models have changes that are not yet reflected in a migration, and so won't be applied.
  Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them.

migrate가 정상적으로 수행되지 않는다. 모델이 변경되면 makemigrations 명령을 먼저 수행한  후에 migrate 명령을 수행해야 한다.

$ python manage.py makemigrations
Migrations for 'pybo':
  pybo\migrations\0001_initial.py
    - Create model Question
    - Create model Answer

makemigrations 명령어는 모델을 생성하거나 모델에 변화가 있을 경우에 실행해 주어야 하는 명령어다. 위 명령어를 수행하면 pybo/migrations/0001_initial.py 라는 파이썬 파일이 자동으로 생성된다.

# Generated by Django 3.1.3 on 2020-12-01 07:00

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Question',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('subject', models.CharField(max_length=200)),
                ('content', models.TextField()),
                ('create_date', models.DateTimeField()),
            ],
        ),
        migrations.CreateModel(
            name='Answer',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('content', models.TextField()),
                ('create_date', models.DateTimeField()),
                ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pybo.question')),
            ],
        ),
    ]

makemigrations 후에 migrate 명령어로 테이블을 생성한다. (makemigrations을 수행하더라도 실제로 테이블이 생성되지는 않는다. 테이블을 실제 생성하는 명령어는 migrate명령을 통해서만 가능하다.)

 

sqlmigrate

migrate 실행시 실제 어떤 쿼리문이 실행되는지 sqlmigrate 명령을 이용하여 확인할 수 있다.

$ python manage.py sqlmigrate pybo 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "pybo_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "subject" varchar(200) NOT NULL, "content" text NOT NULL, "create_date" datetime NOT NULL);
--
-- Create model Answer
--
CREATE TABLE "pybo_answer" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "content" text NOT NULL, "create_date" datetime NOT NULL, "question_id" integer NOT NULL REFERENCES "pybo_question" ("id") 
DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "pybo_answer_question_id_e174c39f" ON "pybo_answer" ("question_id");
COMMIT;

python manage.py sqlmigrate pybo 0001 명령에서 'pybo'는 makemigrations 명령어 수행시 생성되었던 pybo/migrations/0001_initial.py 파일의 마이그레이션명 'pybo'를 의미하고 '0001'은 생성된 파일의 일련번호를 의미한다.

 

migrate

migrate 명령을 수행하여 실제 테이블을 생성한다.

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, pybo, sessions
Running migrations:
  Applying pybo.0001_initial... OK

question과 answer 테이블이 생성된 것을 확인할 수 있다.

Comments