PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Teste de unidade Django falhando para vários esquemas Postgres


Os esquemas não são usados ​​em muitos outros mecanismos de banco de dados. Ao especificar um esquema em seus modelos, você introduziu uma dependência em seu código para postgres.

Existem dois caminhos que você pode seguir para resolver seu problema;

Primeiro, você pode adicionar um caminho de pesquisa padrão ao seu usuário postgres. A desvantagem dessa abordagem é que os esquemas não podem mais ser usados ​​para namespaces, mas a vantagem é que, se seu banco de dados mudar para um mecanismo diferente, seu código funcionará perfeitamente. O namespace de suas tabelas pode ser obtido escolhendo alguma maneira padrão de nomear suas tabelas, semelhante à maneira que o Django faz isso por padrão (por exemplo, appName_className)

Existem duas maneiras de conseguir isso. O comando postgres para fazer isso dessa maneira é:
ALTER USER (your user) SET search_path = "$user",(schema1),(schema2),(schema3),(...)

A maneira somente do django de fazer isso seria:
# 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'
        }
    }
}

Você também vai querer mudar:
db_table = 'cedirData\".\"persons'

para:
db_table = 'persons'

Como bônus, agora você pode usar:
manage.py inspectdb > models.py

que é um bom recurso, dessa forma você não precisa copiar seu banco de dados existente manualmente.

No entanto, esta solução não o ajudará se o namespace do esquema for muito usado em seu banco de dados e outros aplicativos dependerem dele. Uma abordagem diferente seria escrever um testrunner personalizado para criar esses esquemas em seu banco de dados de teste. Isso é um pouco mais complicado do que a abordagem acima e pode ser meio confuso. Eu realmente não recomendo fazer isso, mas se você estiver interessado eu posso tentar ajudar.

Uma maneira menos confusa, mas mais 'hacky' seria simplesmente substituir o meta quando os testes estão sendo executados. Isso também seria um testrunner.
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]

Você também vai querer definir isso como um testrunner em seu arquivo settings.py.