Error when using multiple Bds in Django

Asked

Viewed 82 times

1

Hello

I’m studying how to add two databases in Django and am finding a problem.

When I use the using in the list method, it can use the database chosen and lists the clients in the template.

def listar_clientes():
    clientes = Cliente.objects.using('leitura').all()
    return clientes

But when using the router find next problem:

raise ImproperlyConfigured("settings.DATABASES is improperly configured. 
"
django.core.exceptions.ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings doc
umentation for more details.

Code of the Router:

class Router(object):
    def db_for_read(self, models, **hints):
        return 'leitura'

    def db_for_write(self, models, **hints):
        return 'escrita'

py Settings.:

....


DATABASES = {
    'default': {},
    'escrita': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'tw_django_orm_escrita',
        'USER': 'root',
        'PASSWORD': '1234',
        'HOST': 'localhost',
        'PORT': '3306'
    },
    'leitura': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'tw_django_orm_leitura',
        'USER': 'root',
        'PASSWORD': '1234',
        'HOST': 'localhost',
        'PORT': '3306'
    },
}

DATABASES_ROUTERS = ['clientes.router.Router']

....

I need some help to solve this problem!!

1 answer

1


You need to remove the 'default': {},. He’s trying to find the configuration of "ENGINE" in that dictionary and can’t.

I suggest you leave the default as your writing database and create one with the replica name where the replica is the read.

I like working with the following configuration for production:


DATABASES = {
    "default": {
        "ENGINE": os.getenv("DB_ENGINE", "django.db.backends.sqlite3"),
        "NAME": os.getenv("DB_DATABASE", os.path.join(BASE_DIR, "db.sqlite3")),
        "USER": os.environ.get("DB_USER"),
        "HOST": os.environ.get("DB_HOST"),
        "PORT": os.environ.get("DB_PORT"),
        "PASSWORD": os.environ.get("DB_PASSWORD"),
    }
}

DATABASES["default"]["CONN_MAX_AGE"] = int(os.getenv("DB_CONN_MAX_AGE", 0))  # type: ignore

if os.getenv("USE_REPLICA"):
    DATABASES["replica"] = {
        "ENGINE": os.getenv("DB_ENGINE_REPLICA"),
        "NAME": os.getenv("DB_DATABASE_REPLICA"),
        "USER": os.getenv("DB_USER_REPLICA"),
        "HOST": os.getenv("DB_HOST_REPLICA"),
        "PORT": os.getenv("DB_PORT_REPLICA"),
        "PASSWORD": os.getenv("DB_PASSWORD_REPLICA"),
    }
    DATABASES["replica"]["CONN_MAX_AGE"] = int(os.getenv("DB_CONN_MAX_AGE_REPLICA", 0))  # type: ignore
    DATABASE_ROUTERS = ["MY_PROJECT.support.db_routing.DatabaseRouter"]

My router is:

class DatabaseRouter:
    """
    A router to control all database operations on models in the
    auth application.
    """

    def db_for_read(self, model, **hints):
        """
        Always read from REPLICA database
        """
        return "replica"

    def db_for_write(self, model, **hints):
        """
        Always write to DEFAULT database
        """
        return "default"

    def allow_relation(self, obj1, obj2, **hints):
        """
        Objects from REPLICA and DEFAULT are de same, then True always
        """
        return True

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Only DEFAULT database
        """
        return db == "default"

If you want to keep your setup without the default, you must configure all class methods DatabaseRouter default return by default. Like def allow_migrate(self, db, app_label, model_name=None, **hints):

The official documentation for consultation is: Multiple Databases

  • Perfect!! It worked using the writing bank as default. Thank you very much!!!

  • +1 The answer was good, but it would be nice to add links to the documentation of the concepts you are using. So some other user with similar problems will have better basis to modify and adapt their solution to their problem.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.