PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Échec du test unitaire Django pour plusieurs schémas Postgres

Les schémas ne sont pas utilisés dans de nombreux autres moteurs de base de données. En spécifiant un schéma dans vos modèles, vous avez introduit une dépendance dans votre code pour postgres.

Vous pouvez emprunter deux voies pour résoudre votre problème ;

Tout d'abord, vous pouvez ajouter un chemin de recherche par défaut à votre utilisateur postgres. L'inconvénient de cette approche est que les schémas ne peuvent plus être utilisés pour l'espacement des noms, mais l'avantage est que si votre base de données change de moteur, votre code fonctionnera parfaitement. L'espacement des noms de vos tables peut être obtenu en choisissant une manière standard de nommer vos tables, similaire à la façon dont Django le fait par défaut (par exemple, appName_className)

Il existe deux façons d'y parvenir. La commande postgres pour le faire de cette façon est :

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

La seule façon de le faire avec Django serait :

# 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'
        }
    }
}

Vous voudrez également modifier :

db_table = 'cedirData\".\"persons'

à :

db_table = 'persons'

En bonus, vous pouvez désormais utiliser :

manage.py inspectdb > models.py

ce qui est une fonctionnalité intéressante, de cette façon vous n'avez pas à copier votre base de données existante à la main.

Cette solution ne vous aidera cependant pas si l'espacement de noms de schéma a été largement utilisé sur votre base de données et que d'autres applications en dépendent. Une approche différente consisterait à écrire un testrunner personnalisé pour créer ces schémas dans votre base de données de test. Ceci est un peu plus compliqué que l'approche ci-dessus et peut être un peu désordonné. Je ne recommande pas vraiment de faire cela, mais si cela vous intéresse, je pourrais essayer de vous aider.

Une méthode moins compliquée, mais plus "hacky", consisterait simplement à remplacer la méta lorsque les tests sont en cours d'exécution. Ce serait aussi un testeur.

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]

Vous voudrez également le définir en tant que testrunner dans votre fichier settings.py.