[Django] Model 정의와 Migration
지난 글에서는 hello 라는 django app 을 추가하고 간단한 api 를 추가하고 호출해보는 과정을 진행해보았다. 이번에는 django model 을 추가하고 django 기능을 사용해 database 에 적용하는 과정을 진행해보겠다.
1. Django Model
- django model
django 에는 model 이라는 개념이 있다. model 은 데이터 정보에 대해 정의된 클래스로, 데이터베이스의 테이블에 매핑되는 클래스라고 생각하면 된다. 테이블의 각 컬럼에 매핑되는 속성과 이를 다루는 메서드들을 포함하고 있다. django 의 migration 기능을 통해 model 을 database schema 에 적용할 수 있다.
- model 정의
model 을 정의하기 위해서는 django.db.models.Model 을 사용해야 한다. django model 은 모두 django.db.models.Model 을 상속받은 파이썬 클래스이다. model 의 필드들은 테이블의 컬럼에 매핑되는데, models API 를 통해서 정의된다.
아래는 인사말에 대한 정보를 저장하는 Greeting 이라는 model 을 정의한 코드이다.
# hello/models.py
from django.db import models
class Greeting(models.Model):
country = models.CharField(max_length=100)
greeting = models.CharField(max_length=100)
인사말을 사용하는 나라를 저장하기 위한 country 와 인사말을 저장하기 위한 greeting 이라는 두가지 필드를 가진다. 둘은 모두 문자열을 저장하는 필드로 modles.CharField 를 사용하여 정의되었다.
2. django migration
- include app
정의된 model 을 database 에 적용하기 위해서는 먼저 project 에 해당 app 을 포함시켜야 한다. django project 의 설정은 settings.py 에서 수행된다. settings.py 에는 INSTALLED_APPS 라는 리스트가 있는데, 이 리스트는 현재 project 에 설치된 app 의 목록이다. app 의 설정 클래스 또는 app 을 포함하는 패키지의 이름을 저장해주면 된다.
# myproject/settings.py
INSTALLED_APPS = [
'hello.apps.HelloConfig', # hello app 의 config 클래스
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
INSTALLED_APPS 를 확인하면 기본적으로 django 에서 제공해주는 여러 app 들이 이미 등록되어 있다. 여기에 hello 의 설정 클래스인 hello.apps.HelloConfig 를 추가했다.
- makemigrations
model 정보를 database 에 적용하는 migration 을 수행하기 위해서는 먼저 migration 파일을 생성해야 한다. migration 파일은 model 의 변경사항을 저장하는 파일로 migration 을 실행핧때 해당 파일을 통해 database 테이블의 변경을 수행한다.
migration 파일을 생성하기 위해서는 makemigrations 명령어를 사용한다. 아래의 예시와 같이 makemigrations 뒤에 migration 파일을 생성할 app 의 이름을 붙여주면 된다.
$ python manage.py makemigrations hello
Migrations for 'hello':
hello/migrations/0001_initial.py
+ Create model Greeting
명령어를 실행하면 실행 결과로 Greeting 이라는 model 생성과 함께 hello app 을 위한 0001_initial.py 이라는 파일이 생성된 것을 알 수 있다. 이 파일이 migration 파일로 내용을 확인하면 아래와 같다.
# hello/migrations/0001_initial.py
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Greeting',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('country', models.CharField(max_length=100)),
('greeting', models.CharField(max_length=100)),
],
),
]
migration 파일의 내용을 모두 이해할 수는 없지만 Greeting 이라는 model 이 생성되었고 그 필드로 model 클래스에서 정의한 country, greeting 과 id 가 포함되어 있는 것을 확인할 수 있다.
- sqlmigrate
이제 생성된 migration 파일을 적용해야 하는데, 그 전에 migration 을 수행하면 어떤 쿼리가 실행되는지 미리 알 수 있는 명령어가 있다.
sqlmigrate 명령어를 사용하면 app 의 특정 migration 파일이 실행될 때 어떤 SQL 이 수행되는지 알 수 있다. 아래 예제에서는 앞에서 만들어진 hello app 의 0001 번 migration 파일을 확인해보았다.
$ python manage.py sqlmigrate hello 0001
BEGIN;
--
-- Create model Greeting
--
CREATE TABLE "hello_greeting" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "country" varchar(100) NOT NULL, "greeting" varchar(100) NOT NULL);
COMMIT;
명령어를 실행하면 SQL 문을 결과로 출력한다. 내용은 간단한데, migration 파일에서 확인한 것처럼 id, country, greeting 세가지 필드를 가지는 hello_greeting 이라는 테이블을 생성한다. 테이블의 이름은 기본값으로 {app}_{model name} 인 것을 알 수 있다.
- migrate
이제 migration 기능을 통해 model 정보를 database 에 적용해보겠다. migration 을 실행할 때는 migrate 명령어를 사용하면 된다.
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, hello, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
...
Applying hello.0001_initial... OK
Applying sessions.0001_initial... OK
migrate 명령어를 실행하면 INSTALLED_APPS 에 저장된 모든 app 의 migration 을 수행한다. 예제에서는 project 를 설정하고 처음 migration 을 수행하기 때문에 기본으로 설정된 app 들의 migration 도 모두 수행된다. 수행된 목록을 확인해보면 hello.0001_initial 도 migration 이 수행된 것을 확인할 수 있다.
이쯤되면 migration 이 어떤 database 에 적용되는건지 궁금증이 들 수 있을 것이다. 왜냐하면 따로 django database 설정을 해준적이 없기 때문이다.
django 에서는 기본값으로 SQLite 를 지원한다. 이때문에 migration 등을 수행하면 sqlite 파일이 생성되고 해당 db 파일에 migration 이 수행된다. sqlite db 에 접근해보면 django model 의 테이블들이 생성되어 있고 hello_greeting 테이블도 정의한 컬럼들을 포함하여 생성된 것을 확인할 수 있다.
sqlite> .tables
auth_group django_admin_log
auth_group_permissions django_content_type
auth_permission django_migrations
auth_user django_session
auth_user_groups hello_greeting
auth_user_user_permissions
sqlite> .schema hello_greeting
CREATE TABLE IF NOT EXISTS "hello_greeting" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "country" varchar(100) NOT NULL, "greeting" varchar(100) NOT NULL);
[References]
- https://docs.djangoproject.com/en/6.0/intro/tutorial02/#writing-your-first-django-app-part-2
- https://docs.djangoproject.com/en/6.0/topics/db/models/