본문 바로가기
Develop/Python

Django 여러 개의 데이터베이스 사용하기

by bellsilver7 2023. 4. 4.
728x90

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에 마이그레이션하게 된다.

728x90

댓글