sql >> Base de Datos >  >> RDS >> PostgreSQL

La prueba de unidad de Django falla para múltiples esquemas de Postgres

Los esquemas no se usan en muchos otros motores de base de datos. Al especificar un esquema en sus modelos, introdujo una dependencia en su código para postgres.

Hay dos rutas que puede tomar para resolver su problema;

Primero, podría agregar una ruta de búsqueda predeterminada a su usuario de postgres. La desventaja de este enfoque es que los esquemas ya no se pueden usar para el espacio de nombres, pero la ventaja es que si su base de datos alguna vez cambia a un motor diferente, su código funcionará perfectamente. El espacio de nombres de sus tablas se puede lograr eligiendo alguna forma estándar de nombrar sus tablas, similar a la forma en que Django lo hace de forma predeterminada (por ejemplo, appName_className)

Hay dos maneras de lograr esto. El comando de postgres para hacerlo de esta manera es:

ALTER USER (your user) SET search_path = "$user",(schema1),(schema2),(schema3),(...)

La forma exclusiva de django de hacerlo sería:

# Warning! This is untested, I just glanced at the docs and it looks right.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        # some configuration here
        'OPTIONS': {
            'options': '-c search_path=schema1,schema2,schema3'
        }
    }
}

También querrás cambiar:

db_table = 'cedirData\".\"persons'

a:

db_table = 'persons'

Como beneficio adicional, ahora puede usar:

manage.py inspectdb > models.py

que es una buena característica, de esa manera no tiene que copiar su base de datos existente a mano.

Sin embargo, esta solución no lo ayudará si el espacio de nombres del esquema se usó mucho en su base de datos y otras aplicaciones dependen de él. Un enfoque diferente sería escribir un testrunner personalizado para crear esos esquemas en su base de datos de prueba. Esto es un poco más complicado que el enfoque anterior y puede ser un poco complicado. Realmente no recomiendo hacer esto, pero si estás interesado, podría intentar ayudarte.

Una forma menos complicada, pero más 'hacky', sería simplemente anular meta cuando se ejecutan las pruebas. Este también sería un corredor de pruebas.

from django.test.simple import DjangoTestSuiteRunner
from django.db.models.loading import get_models

class SchemaModelTestRunner(DjangoTestSuiteRunner):
    """Docstring"""
    def setup_test_environment(self, *args, **kwargs):
        self.original_db_tables = {}
        self.schema_models = [m for m in get_models()
                                 if '"."' in m._meta.db_table]
        for m in self.schema_models:
            schema, table = m._meta.db_table.split('"."')
            self.original_db_tables[m] = m._meta.db_table
            m._meta.db_table = 'schema_'+schema+'_table_'+table

        super(SchemaModelTestRunner, self).setup_test_environment(*args,
                                                                   **kwargs)
    def teardown_test_environment(self, *args, **kwargs):
        super(SchemaModelTestRunner, self).teardown_test_environment(*args,
                                                                      **kwargs)
        # reset models
        for m in self.schema_models:
            m._meta.db_table = self.original_db_tables[m]

También querrá definir esto como un corredor de prueba en su archivo settings.py.