Multi-Database Model configuration

1. Define External Database in settings.py of the main application

DATABASES = {
    # Default Local Database.
    "default": {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'local_db_name',
        'USER': 'local_db_user',
        'PASSWORD': 'local_db_passw',
        # ...
    },
    # External Database. <<<
    "external_database":{ # Name to use in-app.
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'external_db_name',
        'USER': 'external_db_user',
        'PASSWORD': 'external_db_passw',
        'HOST': '127.0.0.1', # or external host IP.
        'PORT': '5432'
    },
}

2. Create Manager with Configuration to retrieve from secondary database.

Creating a Custom Manager allows configuring other options with ease.

from django.db.models.manager import BaseManager as Manager
from django.db.models.query import QuerySet

class ExternalDatabaseManager(Manager.from_queryset(QuerySet)):
    use_in_migrations = False # To not override when migrating local application.
    use_db = "external_database" # Name set in Databases dict.

    def get_queryset(self):
        # Return queryset specifying database, otherwise it must be specified in every ORM call.
        return super().get_queryset().using(self.use_db)

3. Override objects property on External Database models.

from django.db import models

from .external_manager import ExternalDatabaseManager

class ExternalApplicationModel(models.Model):
    
    # IMPORTANT:
    class Meta:
        # !! Define `app_label` to separate from main app models.
        app_label = 'external_app' 
        # !! Set `db_table` to the same name in external db.
        db_table = 'external_app_table'
    
    # Overrides with Custom Manager.
    objects = ExternalDatabaseManager()

4. Call Django ORM like always

results_from_external_db = ExternalApplicationModel.objects.all()

Author: Martín Vilche