I am using two databases, one to read data from and then write data to another. Below is my Router class and my changes to settings but am very new to this concept, can someone with more experience in this area confirm that it should work or help make edits?
The application is named "myapp", the read-only database I have named "readonly_db" and the database I want to write to is the "default" database.
class MyappRouter:
def db_for_read(self, model, **hints):
if model._meta.app_label == 'myapp':
return 'readonly_db'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'myapp'
return 'default'
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == obj2._meta.app_label:
return True
else:
return False
return None
def allow_migrate(self, db, **hints):
if db == 'default':
return True
elif db == 'readonly_db':
return False
return None
DATABASE_ROUTERS = ['<path to>.myapprouter.py']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myapp' ,
'USER': 'USER',
'PASSWORD': 'PASSWORD',
'HOST': 'LOCALHOST',
'PORT': '5432'
}
'readonly_db': {
'ENGINE': 'django_postgres_readonly'
'NAME': 'READONLY'
'USER': 'USER'
'PASSWORD': 'PASSWORD'
'HOST': 'LOCALHOST'
'PORT': '5432'
}
You're going the right way. I'll share the solution I have currently running.
settings.py
USE_REPLICA = eval_env_as_boolean("USE_REPLICA", False)
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.getenv("DB_USER"),
"HOST": os.getenv("DB_HOST"),
"PORT": os.getenv("DB_PORT"),
"PASSWORD": os.getenv("DB_PASSWORD"),
}
}
DATABASES["default"]["CONN_MAX_AGE"] = int(os.getenv("DB_CONN_MAX_AGE", 0)) # type: ignore
if 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("DEFAULT_DB_CONN_MAX_AGE_REPLICA", 0)) # type: ignore
DATABASE_ROUTERS = ["my_app.setup.db_routing.DatabaseRouter"]
db_routing.py
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"
Basically you can simplify your router a bit
UPDATE:
USE_REPLICA
exists only as an option so I can quickly disable the read database. Settings.py
runs only at system startup, so the replica configuration is added when the system starts, but only if that variable exists.
About the CONN_MAX_AGE
you can see more here. And here too on checklist for production.