본문 바로가기
python

[python-django]multi databases를 사용하는 방법

by 하이바네 2022. 11. 24.
반응형

django에서 2개 이상의 데이터베이스를 연결하여 사용해야하는 경우가 생길 예정이라 학습중이다.

 

알아야 하는 키워드로는 inspectdb와 database router이다.

 

물론 다른 database를 사용하더라도 현재의 django의 앱에서 모델을 생성하고 DB만 그쪽을 연결 시킨다면 inspectdb를 알 필요는 없다. 하지만 다른 예를 들면 기본 db는 django에서 만들어서 사용을하고, 다른 db는 기존에 생성된 데이터를 쓰겠다. 하는 경우에는 알아야 한다.

 

inspect db

기존에 생성된 테이블을 models.py로 가져올 수 있다. 그럼으로 인해 orm을 사용해서 데이터에 접근을 할 수 있게 된다.

 

database router

어떤 모델을 사용할때 어떤 DB와 연결을 할지 중계를 해주는 역할을 한다.

 

 

Database Router를 사용하는 방법

1. Router파일 생성
 - 예시로는 config폴더 안에 router파일을 생성한다.

 

defaultRouter.py(기본 db로 사용할것)

class DefaultRouter:
    route_app_labels = {}#default router를 사용하는 models.py가 있는 app의 name을 입력
    db_name = 'default'

    def db_for_read(self, model, **hints):
        """
        Attempts to read logs and others models go to primary_db.
        """
        print(model._meta.app_label)
        if model._meta.app_label in self.route_app_labels:
            return self.db_name
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write logs and others models go to primary_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return self.db_name
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the obj1 or obj2 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
        'primary_db' database.
        """
        if app_label in self.route_app_labels:
            return self.db_name
        return None

 

mariadbRouter.py(외부에 존재하는 db를 중계)

#특정 앱의 모델을 중계 다른 db로 연결 시켜준다. 그래서 앱의 이름을 체크하는 형태

class MariadbRouter:
    route_app_labels = {'mariadb'}#MariadbRouter router를 사용하는 app의 name을 입력 ....?
    db_name = 'mariadb'

    def db_for_read(self, model, **hints):
        """
        Attempts to read logs and others models go to primary_db.
        """
        print(model._meta.app_label)
        if model._meta.app_label in self.route_app_labels:
            return self.db_name
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write logs and others models go to primary_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return self.db_name
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the obj1 or obj2 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
        'primary_db' database.
        """
        if app_label in self.route_app_labels:
            return self.db_name
        return None

2. settings.py에 DATABASE_ROUTERS를 설정
 - config폴더 안에 만들었으므로 다음과 같이 설정
 - DATABASE_ROUTER에 적힌 순서에 따라 동작을 하므로, default로 사용하는 것이 앞에 오면 된다.

DATABASE_ROUTERS = ['config.defaultRouter.DefaultRouter', 'config.mariadbRouter.MariadbRouter']

 

3. settings.py에 DATABASE 설정
 - default외에 mariadb라는 것을 추가한 예시

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test1',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST':'localhost',
        'PORT':'3306'
    },
    'mariadb': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST':'localhost',
        'PORT':'13306'
    }
}

 

위와 같이 설정을 하면 이제 반쯤은 왔다고 보면된다. 

여기서 아래와 같이 분기가 될 것이다.

 

선택1. maraidb에 접근해서 사용할것이 특정 앱의 models.py에서 생성을 하고 관리를 하는 형태인지?

선택2. inspectdb로 기존에 만들어진것을 읽어오는 형태로 할 것인지?

 

어떤 선택을 하던지 config 폴더 안에 만든 router파일들의 역할에 대해 아는게 중요하다고 생각한다.(여기서 많이 막혔었다...) 어떤 앱의 모델을 사용하면 router를 통해서 db를 중계하는 역할을 한다.

 

 

만약에 선택1인 경우에는 A라는 앱에 models.py를 만들었고 이거를 mariadbRouter.py를 거치게 하려면 route_app_labels에 A라는 앱의 이름을 적어주면된다.

 

그게 아니라 선택2라는 형태를 취하게 되면 inspectdb를 해서 models.py를 뽑아내고 이거를 특정 앱에 넣는 형태가 될 것이다. 그리고 특정앱은 필자의 경우에는 오직 해당 models.py를 관리하기 위한 모델로 사용을 했다. 그러면 이 경우에는 mariadbRouter.py에서 route_app_labels에는 db를 관리하기 위해 생성한 앱의 이름을 넣어놔야한다. 해당 앱의 모델에 접근을 하는 경우 디폴트가 아닌 다른 db를 사용할 것이기 때문이다.

 

위의 스크린샷을 선택2에 대한 글을 폴더 구조와 함께 보여주기 위해서 넣은것이다. mariadb앱에 있는 test_models.py는 디폴트가 아닌 외부db를 연결을 할 것이고, board라는 앱에서 사용을 할것이다. 하지만 결국 model파일은 mariadb라는 앱에 있으므로 route_app_labels에는 mariadb가 들어가야한다.

 

위의 내용은 필자가 그냥 삽질했던 내용인데 혹시 같이 삽질하는 분이 있으면 도움이 되었으면 한다.

 

inspectdb를 하는 방법에 대해서는 다음 글에서 다뤄보겠다.

728x90

댓글