Package: django-multidb-router
django-multidb-routermultidbprovides two Django database routers useful in primary-replica database
deployments.ReplicaRouterWithmultidb.ReplicaRouterall read queries will go to a replica
database;  all inserts, updates, and deletes will go to thedefaultdatabase.First, defineREPLICA_DATABASESin your settings.  It should be a list of
database aliases that can be found inDATABASES:DATABASES = {
    'default': {...},
    'shadow-1': {...},
    'shadow-2': {...},
}
REPLICA_DATABASES = ['shadow-1', 'shadow-2']Then putmultidb.ReplicaRouterinto DATABASE_ROUTERS:DATABASE_ROUTERS = ('multidb.ReplicaRouter',)The replica databases will be chosen in round-robin fashion.If you want to get a connection to a replica in your app, usemultidb.get_replica:from django.db import connections
import multidb

connection = connections[multidb.get_replica()]PinningReplicaRouterIn some applications, the lag between the primary database receiving a write and its
replication to the replicas is enough to cause inconsistency for the end user.
For example, imagine a scenario with 1 second of replication lag. If a user
makes a forum post (to the primary) and then is redirected to a fully-rendered
view of it (from a replica) 500ms later, the view will fail. If this is a problem
in your application, consider usingmultidb.PinningReplicaRouter. This
router works in combination withmultidb.middleware.PinningRouterMiddlewareto assure that, after writing to thedefaultdatabase, future reads from
the same user agent are directed to thedefaultdatabase for a configurable
length of time.CaveatsPinningRouterMiddlewareidentifies database writes primarily by request
type, assuming that requests with HTTP methods that are notGET,TRACE,HEAD, orOPTIONSare writes. You can indicate that any view writes to
the database by using themultidb.db_writedecorator. This will cause the
same result as if the request were, e.g., aPOST.You can also manually setresponse._db_write = Trueto indicate that a
write occurred. This will not result in using thedefaultdatabase in this
request, but only in the next request.ConfigurationTo usePinningReplicaRouter, put it intoDATABASE_ROUTERSin your
settings:DATABASE_ROUTERS = ('multidb.PinningReplicaRouter',)Then, install the middleware. It must be listed before any other middleware
which performs database writes:MIDDLEWARE_CLASSES = (
    'multidb.middleware.PinningRouterMiddleware',
    ...more middleware here...
)PinningRouterMiddlewareattaches a cookie to any user agent who has just
written. The cookie should be set to expire at a time longer than your
replication lag. By default, its value is a conservative 15 seconds, but it can
be adjusted like so:MULTIDB_PINNING_SECONDS = 5If you need to change the name of the cookie, use theMULTIDB_PINNING_COOKIEsetting:MULTIDB_PINNING_COOKIE = 'multidb_pin_writes'You may also set the ‘Secure’, ‘HttpOnly’, and ‘SameSite’ cookie attributes by
using the following settings. These settings are based on Django’s settings for
the session and CSRF cookies:MULTIDB_PINNING_COOKIE_SECURE = False
MULTIDB_PINNING_COOKIE_HTTPONLY = False
MULTIDB_PINNING_COOKIE_SAMESITE = 'Lax'Note: the ‘SameSite’ attribute is onlyavailable on django 2.1 and higher.use_primary_dbmultidb.pinning.use_primary_dbis both a context manager and a decorator for
wrapping code to use the primary database. You can use it as a context manager:from multidb.pinning import use_primary_db

with use_primary_db:
    touch_the_database()
touch_another_database()or as a decorator:from multidb.pinning import use_primary_db

@use_primary_db
def func(*args, **kw):
    """Touches the primary database."""Running the TestsTo run the tests, you’ll need to install the development requirements:pip install -r requirements.txt
./run.sh testAlternatively, you can run the tests with several versions of Django
and Python using tox:$ pip install tox$ tox