Python, Django with multiple databases

2

To work with several databases in the Laravel framework, once you have configured all the connections in the configuration files, simply define in the model which connection to the database that model will use, and then regardless of the operation the model will always point to a particular bank.

An example is when I have two clients each with their own bank, and I need to perform CRUD on both banks, with Laravel I only have to define which client model to use and the operations are performed normally.

How do I do this using Django?

    
asked by anonymous 17.12.2017 / 22:25

1 answer

1

You'll be able to do this through Automatic Database Routing . It is a rather extensive configuration, but we will use a simple and practical example (removed from the documentation).

This will have some databases: one for app auth and all other apps will use a primary / replica configuration with two replicas just for reading. This would be the configuration for the databases:

DATABASES = {
    'default': {},
    'auth_db': {
        'NAME': 'auth_db',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'swordfish',
    },
    'primary': {
        'NAME': 'primary',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'spam',
    },
    'replica1': {
        'NAME': 'replica1',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'eggs',
    },
    'replica2': {
        'NAME': 'replica2',
        'ENGINE': 'django.db.backends.mysql',
        'USER': 'mysql_user',
        'PASSWORD': 'bacon',
    },
}

Now we're going to have to deal with routing. First let's create a router that will know how to send queries from the app auth to auth_db :

class AuthRouter:
    """
    Um router para controlar todas as operações de banco de
    dados dos models da app auth.
    """
    def db_for_read(self, model, **hints):
        """
        Definição do nome do banco para leitura.
        """
        if model._meta.app_label == 'auth':
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Definição do nome do banco para escrita.
        """
        if model._meta.app_label == 'auth':
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Permite relações se um model na app auth está envolvido.
        """
        if obj1._meta.app_label == 'auth' or \
           obj2._meta.app_label == 'auth':
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Certifica que a app auth aparece apenas no banco 'auth_db'.
        database.
        """
        if app_label == 'auth':
            return db == 'auth_db'
        return None

And here we are going to create a router that will send everything from the other apps to our primary / replica configuration, randomly choosing which replica it will read:

import random

class PrimaryReplicaRouter:
    def db_for_read(self, model, **hints):
        """
        Leitura vai para um dos dois, aleatoriamente.
        """
        return random.choice(['replica1', 'replica2'])

    def db_for_write(self, model, **hints):
        """
        Escrita sempre no primary
        """
        return 'primary'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relações entre objetos são permitidas se ambos objetos
        estão no primary/replica.
        """
        db_list = ('primary', 'replica1', 'replica2')
        if obj1._state.db in db_list and obj2._state.db in db_list:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return True

At the end of it all, you will add DATABASE_ROUTERS to your settings.py project file, with the path to the two previously created classes.

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']

You have this other post that also addresses the same subject.

    
18.12.2017 / 16:28