Django: starting server using a specific database out of multiple databases

I am trying to set up 2 databases in django. The second database is meant for testing purposes, so the 2 databases practically have the same models.

My question is how to start the server using the second database.

The steps I did for setting up the databases:

  1. I created a second app called 'testing', so now in my project root folder there is the app api (the real one) and testing (the app meant for the test database). Afterwards, added the same models from api/models.py to testing/models.py
  2. Created router for the first database and the second database:
class AuthRouter:

  route_app_labels = {'auth', 'contenttypes', 'admin', 'sessions'}

  def db_for_read(self, model, **hints):
      if model._meta.app_label in self.route_app_labels:
          return 'default'
      return None

  def db_for_write(self, model, **hints):
      if model._meta.app_label in self.route_app_labels:
          return 'default'
      return None

  def allow_migrate(self, db, app_label, model_name = None, **hints):
      if app_label in self.route_app_labels:
          return db=='default'
      return None

  def allow_relation(self, obj1, obj2, **hints):
      if (
          obj1._meta.app_label in self.route_app_labels or
          obj2._meta.app_label in self.route_app_labels
      ):
          return True
      return None



class SpotTesting:

    route_app_labels = {'spot_testing'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label == "spot_testing":
            return 'test_db'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == "spot_testing":
            return 'test_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_list = ('primary', 'replica1', 'replica2')
        if obj1._state.db == "spot_testing" and obj2._state.db  == "spot_testing":
            return 'test_db'
        return None

    def allow_migrate(self, db, app_label, model_name = None, **hints):
        if app_label  == "spot_testing":
            return 'test_db'
        return None
  1. Edited api/settings.py:
DATABASE_ROUTERS = [
    'api.routers.db_routers.AuthRouter',
    'api.routers.TestRouter.SpotTesting',
]

DATABASES = {

    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': DBNAME,
        'USER': USER,
        'PASSWORD': PASSWORD,
        'HOST': HOST,
        'PORT': PORT,
    },

    'test_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': "spot_db_testing",
        'USER': USER,
        'PASSWORD': PASSWORD,
        'HOST': HOST,
        'PORT': PORT,
    }
}

  1. Ran python manage.py migrate --database=test_dbThis is how the test db looks after migrations. It looks like the some tables that django would normally create are missing

Now I am not sure what command should I run in order to make django runserver use the test_db instead of the normal one.

Most times, its better to use the easy solutions, it saves time. For your situation, you can create a .env details for the db you will like to use and specify the os.environ credentials to point to.

'default': {
    'ENGINE': os.environ.get(ENGINE, testEngine),
    'NAME': os.environ.get(DBNAME, testDBNameDefault),
    'USER': os.environ.get(USER, testUserDefault),
    'PASSWORD': os.environ.get(PASSWORD, testPasswdDefault),
    'HOST': os.environ.get(HOST, localhost),
    'PORT': os.environ.get(PORT, 5432),
},

try this, no extra code required.

Back to Top