본문 바로가기
Python/Django

[Django] Database Dynamic Access

by 혀나Lee 2016. 11. 14.

큰 프로젝트를 구현하다 보면 한 프로젝트 내에서 여러 데이터베이스와 연결하는 경우가 많다. 기본적으로는 django documents 사이트에 나와있듯이 settings 에 사용할 데이터베이스 정보를 추가해 놓고 using() 을 사용하거나 router.py 파일을 추가하여 데이터베이스에 연결하는 방법이 있다. 하지만, 셀 수 없이 많은 데이터베이스에 다이나믹하게 연결해야 하는 경우는 위와 같은 방식으로 사용하면 안된다. 이 페이지에는 장고 프로젝트에서 다이나믹하게 데이터베이스에 접근하는 방법에 대해 설명할 것이다.


데이터베이스 연결 방법

from django.db import connections


external_db = {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'db_name',
'USER': 'user_name',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '5432',

# DB 스키마 사용시 추가
'OPTIONS': {
'options': '-c search_path=schema_name'
},
}

# DB 연결
connections.databases['db_key'] = external_db


일단 기본적으로 데이터베이스를 다이나믹하게 연결하는 방법은 위와 같다. 기본적인 구현 방법은 같으나, API 를 구현할 때 함수 방식과 클래스 방식 두 가지 방식으로 구현이 가능하기 때문에 나눠서 설명하겠다.


먼저, models.py에 테스트를 위한 model 을 추가해 주고 django-rest-framework 라이브러리를 설치해 준다.

함수(def) 방식

from django.core import serializers
from django.db import connections
from django.http JsonResponse
from rest_framework.decorators import api_view
from rest_framework.response import Response

from .models import TestTable


@api_view(['GET])
def test(request):
db_name = request.query_params.get('db_name', None)
schema = request.query_params.get('schema', None)

if db_name and schema:
external_db = {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': db_name,
'USER': 'user_name',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '5432',

# DB 스키마 사용시 추가
'OPTIONS': {
'options': '-c search_path=' + schema
},
}

# DB 연결
connections.databases[db_name] = external_db

# 데이터 조회
test = TestTable.objects.using(db_name).all()
return JsonResponse(serializers.serializer('json', test), safe=False)
return Response({})

다이나믹하게 접근하기 위해 파라미터로 db_name, schema 정보를 받았고 두 개의 파라미터를 잘 받았을 시에 테이블의 모든 데이터를 조회해온다.

클래스(class) 방식

from django.db import connections
from rest_framework.viewsets import ReadOnlyModelViewSet

from .models import TestTable
from .serializers import TradeSerializer


class TestViewSet(ReadOnlyModelViewSet):
queryset = TestTable.objects.all()

def get_serializer_class(self):
return TestSerializer

def get_queryset(self):
db_name = request.query_params.get('db_name', None)
schema = request.query_params.get('schema', None)

if db_name and schema:
external_db = {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': db_name,
'USER': 'user_name',
'PASSWORD': 'password',
'HOST': '127.0.0.1',
'PORT': '5432',

# DB 스키마 사용시 추가
'OPTIONS': {
'options': '-c search_path=' + schema
},
}

# DB 연결
connections.databases[db_name] = external_db

# 데이터 조회
return TestTable.objects.using(db_name).all()
return TestTable.objects.all()

def list(self, request, *args, **kwargs):
return super(TestViewSet, self).list(request, *args, **kwargs)

class 형식을 사용할 때는 queryset 을 받아오는 함수인 get_queryset() 를 추가해 줘야 한다.


댓글