sql >> Databasteknik >  >> RDS >> PostgreSQL

Django-enhetstest misslyckas för flera Postgres-scheman

Scheman används inte i många andra DB-motorer. Genom att ange ett schema i dina modeller har du infört ett beroende i din kod för postgres.

Det finns två vägar du kan ta för att lösa ditt problem;

Först kan du lägga till en standardsökväg för din postgres-användare. Nackdelen med detta tillvägagångssätt är att scheman inte längre kan användas för namnavstånd, men fördelen är att om din databas någonsin ändras till en annan motor kommer din kod att fungera bra. Namnavstånd till dina tabeller kan uppnås genom att välja något standardsätt för att namnge dina tabeller, liknande det sätt som Django gör det som standard (t.ex. appName_className)

Det finns två sätt att uppnå detta. Postgres-kommandot för att göra det på detta sätt är:

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

Det enda sättet att göra det på django skulle vara:

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

Du vill också ändra:

db_table = 'cedirData\".\"persons'

till:

db_table = 'persons'

Som en bonus kan du nu använda:

manage.py inspectdb > models.py

vilket är en trevlig funktion, på så sätt behöver du inte kopiera din befintliga databas för hand.

Den här lösningen kommer dock inte att hjälpa dig om schemanamnavstånd användes flitigt i din databas och andra applikationer förlitar sig på det. Ett annat tillvägagångssätt skulle vara att skriva en anpassad testrunner för att skapa dessa scheman i din testdatabas. Detta är något mer involverat än ovanstående tillvägagångssätt och kan vara lite rörigt. Jag rekommenderar verkligen inte att du gör det här, men om du är intresserad kan jag försöka hjälpa till.

Ett mindre rörigt, men mer "hackigt" sätt skulle vara att helt enkelt åsidosätta meta när tester körs. Detta skulle också vara en 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]

Du kommer också att vilja definiera detta som en testrunner i filen settings.py.




  1. Anropar skalskript från PL/SQL, men skal körs som grid-användare, inte oracle

  2. Hur man subtraherar ett år från ett datum i MariaDB

  3. Den mest effektiva metoden för att upptäcka kolumnändring i MS SQL Server

  4. Uppdatera eller infoga (flera rader och kolumner) från underfråga i PostgreSQL