PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Test jednostkowy Django nie powiódł się dla wielu schematów Postgres

Schematy nie są używane w wielu innych silnikach DB. Określając schemat w swoich modelach, wprowadziłeś w swoim kodzie zależność dla postgresa.

Istnieją dwie drogi, którymi możesz się zająć, aby rozwiązać swój problem;

Po pierwsze, możesz dodać domyślną ścieżkę wyszukiwania do swojego użytkownika postgres. Wadą tego podejścia jest to, że schematów nie można już używać do przestrzeni nazw, ale zaletą jest to, że jeśli baza danych zmieni się na inny aparat, kod będzie działał poprawnie. Przestrzenie nazw tabel można uzyskać, wybierając standardowy sposób nadawania nazw tabelom, podobny do sposobu, w jaki Django robi to domyślnie (np. nazwa_aplikacji_nazwa_klasy)

Można to osiągnąć na dwa sposoby. Polecenie postgres, aby zrobić to w ten sposób, to:

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

Jedynym sposobem na zrobienie tego przez django byłoby:

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

Będziesz także chciał zmienić:

db_table = 'cedirData\".\"persons'

do:

db_table = 'persons'

Jako bonus możesz teraz użyć:

manage.py inspectdb > models.py

co jest fajną funkcją, dzięki czemu nie musisz ręcznie kopiować istniejącej bazy danych.

To rozwiązanie nie pomoże jednak, jeśli przestrzeń nazw schematu była intensywnie wykorzystywana w Twojej bazie danych i inne aplikacje na niej polegają. Innym podejściem byłoby napisanie niestandardowego testrunnera, aby utworzyć te schematy w testowej bazie danych. Jest to nieco bardziej skomplikowane niż powyższe podejście i może być trochę niechlujne. Naprawdę nie polecam tego robić, ale jeśli jesteś zainteresowany, mogę spróbować pomóc.

Mniej niechlujnym, ale bardziej „hackowym” sposobem byłoby po prostu nadpisanie meta podczas uruchamiania testów. Byłby to również 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]

Będziesz także chciał zdefiniować to jako testrunner w swoim pliku settings.py.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zapobiegaj wstrzykiwaniu SQL w dynamicznych nazwach kolumn

  2. PostgreSQL DATEADD() Odpowiednik

  3. Wstawianie liczby zmiennoprzecinkowej do tabeli za pomocą libpq

  4. Wyodrębnij ostatni wiersz z Postgresql dla każdego identyfikatora

  5. Jak AT TIME ZONE działa w PostgreSQL