settings.py의 DATABASES에 DB 정보를 추가하는 것으로 여러 개의 데이터베이스를 연결을 가능하게 할 수 있다.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
},
'db1': {
'ENGINE': os.getenv('DB1_ENGINE'),
'NAME': os.getenv('DB1_NAME'),
'USER': os.getenv('DB1_USER'),
'PASSWORD': os.getenv('DB1_PASSWORD'),
'HOST': os.getenv('DB1_HOST'),
'PORT': os.getenv('DB1_PORT'),
},
'db2': {
'ENGINE': os.getenv('DB2_ENGINE'),
'NAME': os.getenv('DB2_NAME'),
'USER': os.getenv('DB2_USER'),
'PASSWORD': os.getenv('DB2_PASSWORD'),
'HOST': os.getenv('DB2_HOST'),
'PORT': os.getenv('DB2_PORT'),
},
}
여기서 각각의 DB에 마이그레이션을 해야 한다면 어떻게 해야할까?
app1과 app2의 models.py에 아래와 같은 Sample1Model과 Sample2Model이 각각 존재한다.
class Sample1Model(models.Model):
title = models.CharField()
class Sample2Model(models.Model):
title = models.CharField()
이 때 각각의 테이블을 db1과 db2에 migrate하고자 한다.
DATABASE_ROUTERS를 사용해 이를 해결할 수 있다. 먼저 라우터를 생성해보자.
config/db_router.py
class App1Router:
"""
A router to control all database operations on models in the
auth and contenttypes applications.
"""
route_app_labels = {'app1'}
def db_for_read(self, model, **hints):
"""
Attempts to read auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'db1'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'db1'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.app_label in self.route_app_labels or
obj2._meta.app_label in self.route_app_labels
):
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth and contenttypes apps only appear in the
'auth_db' database.
"""
if app_label in self.route_app_labels:
return db == 'db1'
return None
class App2Router:
"""
A router to control all database operations on models in the
auth and contenttypes applications.
"""
route_app_labels = {'app2'}
def db_for_read(self, model, **hints):
"""
Attempts to read auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'db2'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'db2'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.app_label in self.route_app_labels or
obj2._meta.app_label in self.route_app_labels
):
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth and contenttypes apps only appear in the
'auth_db' database.
"""
if app_label in self.route_app_labels:
return db == 'db2'
return None
app1과 app2의 DB를 db1과 db2와 연결하기 위해 2개의 라우터를 생성했다. 다음으로 이 라우터를 settings.py에 등록해줘야 한다.
config/settings.py
DATABASE_ROUTERS = [
'config.db_router.App1Router',
'config.db_router.App2Router',
]
DATABASE_APPS_MAPPING = {
'app1': 'db1',
'app2': 'db2',
}
DATABASES = {
...
}
위와 같이 DATABASE_ROUTERS에 생성한 라우터를 등록하고 DATABASE_APPS_MAPPING에 app과 db를 맵핑해줘야 한다. 이제 models.py를 열어 맵핑한 app_label을 모델에 설정해준다.
app1/models.py
class Sample1Model(models.Model):
title = models.CharField()
class Meta:
app_label = 'app1'
app2/models.py
class Sample2Model(models.Model):
title = models.CharField()
class Meta:
app_label = 'app2'
여기까지 설정은 끝났고 마이그레이션을 진행해본다.
(venv)$ python manage.py migrate --database=db1
--database 옵션을 설정해 특정 DB에 마이그레이션을 할 수 있다. 하지만 여기서 주목해야 할 점은 내가 원하는 테이블만 생성되길 원했지만 django에서 제공하는 몇 가지 테이블이 함께 생성되게 된다. 이를 해결하기 위해서 앱 이름을 함께 명령하면 된다.
(venv)$ python manage.py migrate app1 --database=db1
(venv)$ python manage.py migrate app2 --database=db2
이렇게 하면 특정 앱에 작성된 migrations를 참조하여 해당 DB에 마이그레이션하게 된다.
'Develop > Python' 카테고리의 다른 글
Django command (0) | 2023.12.02 |
---|---|
objc[1466]: +[__NSPlaceholderDate initialize] may have been in progress in another thread when fork() was called. (0) | 2023.07.14 |
[Python] ERROR: Could not find a version that satisfies the requirement yaml (0) | 2022.09.29 |
[Solved] "SyntaxError: Non-ASCII character '\xeb' in file" in python (0) | 2022.08.08 |
Python 파이썬 | #2 설치하기 (0) | 2020.03.07 |
댓글