Django Multi-App Database Router not working
<p>I'm doing a project using Django 1.10 and Python 2.7.</p>

<p>I have read and tried to implement database routing according to <a href="https://docs.djangoproject.com/en/1.10/topics/db/multi-db/#using-routers" rel="nofollow">this page</a>. I have also read up on a lot of different tutorials and other stackoverflow questions. However, I can't seem to get it to work. </p>

<p>This is the scenario that I have:</p>

<p>I need all analytics, auth and admin apps models on the default database. Then cancellation app on a separate database, and driveractivity app on another separate database.</p>

<p>This is the router that I'm using:</p>

<pre><code>from django.conf import settings


class AppRouter:
    def db_for_read(self, model, **hints):
        if model._meta.app_label == 'analytics':
            return 'default'

        elif model._meta.app_label == 'cancellation':
            return 'cancellations_db'

        elif model._meta.app_label == 'driveractivity':
            return 'driveractivity_db'

        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == 'analytics':
            return 'default'

        elif model._meta.app_label == 'cancellation':
            return 'cancellations_db'

        elif model._meta.app_label == 'driveractivity':
            return 'driveractivity_db'

        return None

    def allow_migrate(self, db, app_label, model=None, **hints):    
        if app_label == 'cancellation' and db == 'cancellations_db':
            return True

        if app_label == 'driveractivity' and db == 'driveractivity_db':
            return True

        if app_label in ('analytics', 'auth', 'admin', 'contenttypes', 'sessions', 'rest_framework') and db == 'default':
            return True

        return False
</code></pre>

<p>My database settings are as follows (<strong>settings.py</strong>): </p>

<pre><code>DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'NAME': 'analytics',
        'USER': 'root'
    },
    'driveractivity_db': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'NAME': 'driveractivity',
        'USER': 'root',
    },
    'cancellations_db': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': 'localhost',
        'PORT': '3306',
        'NAME': 'teke_cancellation',
        'USER': 'root'
    }
}

DATABASE_ROUTERS = ['analytics.AppRouter.AppRouter']

DB_Mapping = {
    "cancellation": "cancellations_db",
    "driveractivity": "driveractivity_db"
}
</code></pre>

<p><strong>models.py - cancellation</strong></p>

<pre><code>class Cancellation(models.Model):
    id = models.IntegerField(primary_key=True)
    user = models.EmailField(max_length=255,blank=False)
    time = models.DateField(blank=False)
        created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'


class PenaltyType(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=255,blank=False)
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'


class Penalty(models.Model):
    id = models.IntegerField(primary_key=True)
    user = models.EmailField(max_length=255,blank=False)
    meted = models.BooleanField(default=False)
    penalty_type = models.ForeignKey(PenaltyType)
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'cancellation'
</code></pre>

<p><strong>models.py - driveractivity</strong></p>

<pre><code>class Activity(models.Model):
    email = models.EmailField(null=False)
    driver_name = models.CharField(max_length=30,null=False)
    vehicle_reg = models.CharField(max_length=30,null=False)
    status = models.CharField(max_length=15)
    desc = models.CharField(max_length=250)
    lng = models.FloatField()
    lat = models.FloatField()
    time = models.DateTimeField()
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'driveractivity'


class DistanceDetails(models.Model):
    email = models.EmailField(null=False)
    driver_name = models.CharField(max_length=30,null=False)
    vehicle_reg = models.CharField(max_length=30,null=False)
    new_lng = models.FloatField()
    new_lat = models.FloatField()
    last_state = models.CharField(max_length=15,null=False)
    last_lng = models.FloatField()
    last_lat = models.FloatField()
    created_at = models.DateTimeField(auto_now=True,auto_now_add=False)
    updated_at = models.DateTimeField(auto_now=False,auto_now_add=True)

    class Meta:
        app_label = 'driveractivity'
</code></pre>

<p>Edited <strong>router.py</strong></p>

<pre><code>class AppRouter(object):
    def db_for_read(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')

    def db_for_write(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label in DB_Mapping.keys() or db in DB_Mapping.values():
            return True
        else:
            return None
</code></pre>

<p>Is there something I'm doing wrong?</p>

<p>check if this works for you:</p>

<p><strong>settings.py</strong></p>

<pre><code>DB_Mapping = {
    "cancellation": "cancellation_db",
    "driveractivity": "driveractivity_db",
    ...
}
</code></pre>

<p><strong>router.py</strong></p>

<pre><code>from project.settings import DB_Mapping

class MyRouter(object):
    def db_for_read(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')

    def db_for_write(self, model, **hints):
        return DB_Mapping.get(model._meta.app_label, 'default')
</code></pre>

<p>i do use a similar setup where i route to a different database user based on the group of the user who's making the request.</p>

<p>the allow_migrate can also be written similarly., where if the <code>db == 'default'</code> or <code>if model._meta.app_label in DB_Mapping.keys() or db in DB_Mapping.values(): return True else False</code></p>

python django