PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Django-Einheitentest schlägt für mehrere Postgres-Schemas fehl

Schemata werden in vielen anderen DB-Engines nicht verwendet. Durch die Angabe eines Schemas in Ihren Modellen haben Sie eine Abhängigkeit in Ihren Code für Postgres eingeführt.

Es gibt zwei Möglichkeiten, Ihr Problem zu lösen;

Zunächst könnten Sie Ihrem Postgres-Benutzer einen Standardsuchpfad hinzufügen. Der Nachteil dieses Ansatzes besteht darin, dass Schemas nicht mehr für die Namensraumbildung verwendet werden können, aber der Vorteil besteht darin, dass Ihr Code problemlos funktioniert, wenn Ihre Datenbank jemals auf eine andere Engine umgestellt wird. Das Benennen Ihrer Tabellen kann erreicht werden, indem Sie eine Standardmethode zum Benennen Ihrer Tabellen auswählen, ähnlich wie Django es standardmäßig tut (z. B. appName_className)

Es gibt zwei Möglichkeiten, dies zu erreichen. Der Postgres-Befehl, um dies auf diese Weise zu tun, lautet:

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

Der Django-only-Weg wäre:

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

Sie sollten auch Folgendes ändern:

db_table = 'cedirData\".\"persons'

zu:

db_table = 'persons'

Als Bonus können Sie jetzt Folgendes verwenden:

manage.py inspectdb > models.py

Das ist ein nettes Feature, auf diese Weise müssen Sie Ihre vorhandene Datenbank nicht von Hand kopieren.

Diese Lösung wird Ihnen jedoch nicht helfen, wenn Schema-Namensräume in Ihrer Datenbank stark verwendet wurden und andere Anwendungen darauf angewiesen sind. Ein anderer Ansatz wäre, einen benutzerdefinierten Testrunner zu schreiben, um diese Schemas in Ihrer Testdatenbank zu erstellen. Dies ist etwas komplizierter als der obige Ansatz und kann etwas chaotisch sein. Ich empfehle das nicht wirklich, aber wenn Sie interessiert sind, könnte ich versuchen zu helfen.

Ein weniger chaotischer, aber "hackigerer" Weg wäre, Meta einfach zu überschreiben, wenn Tests ausgeführt werden. Dies wäre auch ein 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]

Sie sollten dies auch als Testrunner in Ihrer settings.py-Datei definieren.