[Python-es] migraciones con multiples bases de datos en django

Pau Cervera pau.cervera en gmail.com
Vie Mayo 6 07:13:51 EDT 2022


Buenas,

Tengo una duda sobre cómo maneja Django las migraciones con múltiples
bases de datos.En mi caso tengo dos DATABASES en el  settings

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'producto',
    },
    'legacy': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'legacy-schema',
    }
}

la DB default está manejada por django desde siempre y la legacy tiene
modelos generados vía inspecdb en una django application que también se
llama legacy. En un principio la BD legacy era de sólo lectura, con lo que
tener los modelos con managed = False (cómo los genera inspectdb) ya estaba
bien.

Con este sistema, y aunque el managed = False, django genera entradas en la
tabla django_migrations para legacy (pués está instalada) aunque no genera
tablas (el comando sqlmigrate sale con SQL vacío), cosa que está bien
porqué están en otra BD.

El problema que tengo ahora es que quiero empezar a gestionar los modelos
de legacy des de Django. Esto supone cambiar los managed = False por
managed = True y a partir de ahí cambiar los modelos. Por ejemplo, añadir
una columna a una tabla.

A priori esto genera una migración de cambio de metadatos de managed =
False a managed = True y después una migración normal que añade la columna
al schema.

Para gestionar a qué BD pertenecen las tablas tengo un custom database
router cómo este:

class LegacyRouter:
    route_app_labels = {'legacy',}
    legacy_database = 'legacy'

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return self.legacy_database
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return self.legacy_database
        return None

    def allow_relation(self, obj1, obj2, **hints):
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        is_legacy_db = db == self.legacy_database
        is_legacy_app = app_label in self.route_app_labels
        if is_legacy_db:
            return is_legacy_app
        else:
            return not is_legacy_app

De esta forma, si ejecuto las migraciones con

python manage.py migrate

se migran las tablas que no son de la BD legacy y no son de la aplicación
legacy. Pero además se incluyen migraciones (con SQL vacío) de los modelos
de legacy.

De la misma forma, si migro los modelos de legacy con

python manage.py migrate --database=legacy

se migran los modelos de legacy, pero además, se añaden entradas para todas
las migraciones de las otras aplicaciones instaladas (sin SQL, con lo que
no se crean/modifican tablas que no tocan).

En ambos casos, python manage.py showmigrations y python manage.py
showmigrations --database=legacy muestran todas las aplicaciones.

Creo que esto es comportamiento esperado, pero ¿hay forma de que no salgan
los modelos en las bases de datos que no los necesitan? ¿Estoy haciendo
algo mal?

¡Muchas gracias!

-----
Pau

Python..., what else?
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <https://mail.python.org/pipermail/python-es/attachments/20220506/8e6a6ee6/attachment.html>


Más información sobre la lista de distribución Python-es