Opened 2 years ago

Closed 2 years ago

Last modified 2 years ago

#34121 closed Bug (invalid)

Multi Databases documenation example doesn't work

Reported by: Jan Przychodniak Owned by: nobody
Component: Database layer (models, ORM) Version: 4.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have been following this documentation:

https://docs.djangoproject.com/en/4.1/topics/db/multi-db/

Here's my Router setup:

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    route_app_labels = ('auth', 'contenttypes')
    TARGET_DB = 'users'

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return self.TARGET_DB
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return self.TARGET_DB
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == self.TARGET_DB
        return None

Here are my settings (kept everything else default):

DATABASES = {
    'default': {
        'HOST': 'localhost',
        'NAME': 'dev01',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres',
        'PASSWORD': 'Admin123!',
        'PORT': '5432',
    },
    'users': {
        'HOST': 'localhost',
        'NAME': 'dev01',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres',
        'PASSWORD': 'Admin123!',
        'PORT': '5433',
    }
}

DATABASE_ROUTERS = ['multidb.routers.AuthRouter']

Migrations are applied correctly on "users" database, however when attempting to apply them on default databse I get an error during Applying admin.0001_initial...Traceback (most recent call last):

Error states: django.db.utils.ProgrammingError: relation "django_content_type" does not exist

Well, logically so - such table is not present in this database. But I defined the router exactly as the documentation told me to. Therefore based on what I see in the documentation I labeled it as a bug in this report.

Change History (3)

comment:1 by Mariusz Felisiak, 2 years ago

Resolution: invalid
Status: newclosed

Well, logically so - such table is not present in this database. But I defined the router exactly as the documentation told me to. Therefore based on what I see in the documentation I labeled it as a bug in this report.

All contrib apps must be together in one database, as cross-database relations are not supported. It's documented on the same page:

"your routers must handle the names of all apps in INSTALLED_APPS before you migrate. See Behavior of contrib apps for information about contrib apps that must be together in one database."

comment:2 by Jan Przychodniak, 2 years ago

It's ​documented on the same page:

"your routers must handle the names of all apps in INSTALLED_APPS before you migrate. See ​Behavior of contrib apps for information about contrib apps that must be together in one database."

It is, but I never reached this part, because I got stuck earlier in the example. When the docs asked me to:

With this setup installed, and all databases migrated as per Synchronizing your databases, lets run some Django code:

Which as far as I understand I need to perform migrations first to be able to run the code. Which migrations I cannot perform based on the example presented.

I would kindly suggest the example could be updated to mention that you need to include all the contrib apps in the same database before asking me to perform the migrations based on the example which never included an app like "django.contrib.admin" in the router.

Mind you, 'django.contrib.admin' is included in INSTALLED_APPS by default. I didn't change anything in the settings apart from the piece of code I sent here.

comment:3 by Mariusz Felisiak, 2 years ago

I would kindly suggest the example could be updated to mention that you need to include all the contrib apps in the same database before asking me to perform the migrations based on the example which never included an app like "django.contrib.admin" in the router.

This section already warns at the very beginning:

"Example purposes only!

This example is intended as a demonstration of how the router infrastructure can be used to alter database usage. It intentionally ignores some complex issues in order to demonstrate how routers are used.

This example won’t work if any of the models in myapp contain relationships to models outside of the other database. Cross-database relationships introduce referential integrity problems that Django can’t currently handle.

Of course, if you have a suggestion for clearer wording, please submit PR.

Note: See TracTickets for help on using tickets.
Back to Top