지난 번에는 DB에 수동으로 테이블을 생성한 뒤 inspectdb
명령을 통해서 만들어진 모델을 이용해서 테이블에 데이터를 삽입해 봤다면, 이번에는 모델을 통해 테이블 생성 및 데이터 삽입하는 방법을 알아보겠습니다.
먼저 models.py에 신규로 생성할 테이블의 모델을 추가합니다.
from django.db import models
...
class TestBookCategory(models.Model):
categoryName = models.CharField(max_length=20)
class TestBook(models.Model):
title = models.CharField(max_length=200)
category = models.ForeignKey(TestBookCategory, on_delete=models.SET_NULL, null=True)
price = models.IntegerField()
reg_datetime = models.DateTimeField()
...
데이터베이스의 각 필드는 Field
클래스의 인스턴스로 표현합니다. 이 작업을 통해 각 필드가 어떤 자료형을 가질 수 있는지를 Django에게 말해줍니다.
CharField : 문자(character)형 타입 필드
DateTimeField : 날짜와 시간형 타입 필드
IntegerField : 정수형 타입 필드
AutoField : 자동증가하는 정수형 타입 필드, 주로 pk를 저장할 때 사용하지만 django 내부적으로 id라는 컬럼을 자동생성하므로, A model can't have more than one AutoField 에러가 발생할 수 있습니다. 이를 방지하려면 id를 생성하지 않고 해당 필드가 PK가 되도록 primary_key=True
옵션을 추가해야 합니다.
ex) category_id = models.AutoField(primary_key=True
)
이 외의 필드 타입에 대한 내용은 다음 링크를 참고하여 사용하도록 합니다.
ForeignKey 클래스를 통해 테이블 간의 관계를 설정할 수도 있습니다.
Django 는 다-대-일(many-to-one), 다-대-다(many-to-many), 일-대-일(one-to-one) 과 같은 모든 일반 데이터베이스의 관계들를 지원합니다.
이 모델을 통해 Django에서는 다음과 같은 작업을 진행합니다.
위 작업을 하기 위해 먼저 test_project프로젝트 내 settings.py
파일의 INSTALLED_APPS
에 앱의 구성 클래스에 대한 참조를 추가하여 test_app앱이 설치되어 있다는 것을 알려줍니다.
이 구성 클래스는 앱이름 + Config이라는 이름으로 생성되어 있으며, test_app/apps.py
파일 내에 존재합니다.
이 내용을 바탕으로 INSTALLED_APPS
에 구성 클래스를 추가합니다. (이전 포스팅에서 test_app
패키지를 통으로 넣어줬다면 별도로 작업하지 않아도 됩니다.)
INSTALLED_APPS = [
"test_app.apps.TestAppConfig",
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Django에 test_app앱이 포함된 것을 알려줬다면 다음 명령을 실행합니다.
$ python manage.py makemigrations test_app
makemigrations
을 실행하게 되면 모델을 생성 혹은 변경시킨 사실과 이 변경사항을 migration
으로 저장시키고 싶다는 것을 Django에게 알려주게 됩니다.
Migration
은 Django가 모델(즉, 데이터베이스 스키마)의 변경사항을 디스크에 저장하는 방법입니다.
test_app/migrations/0001_initial.py
파일에 변경된 새 모델에 대한 migration을 읽어 볼 수 있습니다. 이 파일을 직접 수정할 수 있도록 설계가 되어 있어 Django의 변경점을 수동으로 수정할 수도 있습니다.
다음으로 sqlmigrate
명령을 통해 Migration
이 내부적으로 어떤 SQL 문장을 실행하는지 살펴 볼 수 있습니다.
$ python manage.py sqlmigrate test_app 0001
저의 경우에는 MySQL을 연동하여 다음과 같이 쿼리가 표시되며 이 내용은 연동하는 DB마다 다를 수 있습니다.
sqlmigrate
은 실제로 DB에 마이그레이션이 되지 않고 화면에 출력해줍니다. 단지 마이그레이션에 사용할 SQL문을 보여주는 것이며, 내가 작성한 테이블 모델이 어떻게 db에 마이그레이션이 될지 확인하는 용도로 유용하게 사용할 수 있습니다.
--
-- Create model TestBookCategory
--
CREATE TABLE `core_testbookcategory` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `categoryName` varchar(20) NOT NULL);
--
-- Create model TestBook
--
CREATE TABLE `core_testbook` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `title` varchar(200) NOT NULL, `price` integer NOT NULL, `reg_datetime` datetime(6) NOT NULL, `category_id` bigint NULL);
ALTER TABLE `core_testbook` ADD CONSTRAINT `core_testbook_category_id_11be1c0d_fk_core_testbookcategory_id` FOREIGN KEY (`category_id`) REFERENCES `core_testbookcategory` (`id`);
sqlmigrate
로 출력된 쿼리를 실제로 적용하려면 migrate
명령을 사용합니다.
$ python manage.py migrate
migrate
명령은 아직 적용되지 않은 마이그레이션을 모두 수집해서 실행하며, 이 과정을 통해 모델에서의 변경 사항들과 데이터베이스의 스키마의 동기화가 이루어집니다.
django의 이 강력한 기능은 DB나 테이블을 거의 직접 다루지 않고도 모델을 생성하고 반복적인 변경도 가능하게 해줍니다. 게다가 동작 중인 데이터베이스를 자료 손실 없이 업그레이드하는데 최적화 되어 있습니다.
이 일련의 작업들이 복잡해 보일 수도 있지만 이 단계만 기억하면 됩니다.
makemigrations
을 통해 이 변경사항에 대한 마이그레이션을 생성합니다.migrate
명령을 통해 변경사항을 데이터베이스에 적용합니다.