Opened 9 years ago
Closed 9 years ago
#26540 closed Bug (duplicate)
Can't run tests without "default" connection set
Reported by: | Marcin Nowak | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
According to use cases described in #19775 and #16752 I'm using project with explicit db routing and no "default" connection.
When I'm trying to run tests with empty 'default' connection, I'm getting:
Traceback (most recent call last): File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 946, in setUpClass if not connections_support_transactions(): File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 911, in connections_support_transactions for conn in connections.all()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 911, in <genexpr> for conn in connections.all()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/utils/functional.py", line 59, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/base/features.py", line 216, in supports_transactions with self.connection.cursor() as cursor: File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/base/base.py", line 164, in cursor cursor = self.make_cursor(self._cursor()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/dummy/base.py", line 21, in complain raise ImproperlyConfigured("settings.DATABASES is improperly configured. " ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
When running without "default" key configured, I'm getting an error probably on the first attempt to get specific connection (not the "default" one):
[...] File "/home/marcin/myproject/etl/analysis/etltoolkit.py", line 1098, in dimension_factory sequencer = sequencer or SurrogateKeySequencer(dwhmodel) File "/home/marcin/myproject/etl/analysis/etltoolkit.py", line 739, in __init__ self.connection = connection or connections['etlstg'] File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/utils.py", line 237, in __getitem__ self.ensure_defaults(alias) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/utils.py", line 168, in ensure_defaults conn = self.databases[alias] File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/utils/functional.py", line 59, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/utils.py", line 159, in databases raise ImproperlyConfigured("You must define a '%s' database" % DEFAULT_DB_ALIAS) django.core.exceptions.ImproperlyConfigured: You must define a 'default' database
The bug lies in ConnectionHandler.databases()
:
def databases(self): if self._databases is None: self._databases = settings.DATABASES if self._databases == {}: self._databases = { DEFAULT_DB_ALIAS: { 'ENGINE': 'django.db.backends.dummy', }, } if DEFAULT_DB_ALIAS not in self._databases: raise ImproperlyConfigured("You must define a '%s' database" % DEFAULT_DB_ALIAS) return self._databases
When ensure_defaults()
asks for specified connection (in my case - "etlstg" alias), the databases()
is called as a property getter and checks existence of DEFAULT_DB_ALIAS.
Please do not force us to use DEFAULT_DB_ALIAS if you won't allow to rename it in settings (#26197).
Change History (3)
comment:1 by , 9 years ago
comment:2 by , 9 years ago
Setting dummy
backend results:
Traceback (most recent call last): File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 946, in setUpClass if not connections_support_transactions(): File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 911, in connections_support_transactions for conn in connections.all()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/test/testcases.py", line 911, in <genexpr> for conn in connections.all()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/utils/functional.py", line 59, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/base/features.py", line 216, in supports_transactions with self.connection.cursor() as cursor: File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/base/base.py", line 164, in cursor cursor = self.make_cursor(self._cursor()) File "/home/marcin/myproject/eggs/Django-1.8.6-py2.7.egg/django/db/backends/dummy/base.py", line 21, in complain raise ImproperlyConfigured("settings.DATABASES is improperly configured. " ImproperlyConfigured: settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
The fact that the default database is mandatory is documented in the DATABASES setting
Yes, but it looks like it could be empty before (?) - #19775.
There are still places in Django core code depending on a default database (See #13528 for example).
Yes, also during models registration the default connection is used to truncate table names (or something like that). The sqlite3 handler (my "default") is preparing some stuff for postgres and mysql (in my case). It seems that db router is not used at this stage.
comment:3 by , 9 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
The fact that the
default
database is mandatory is documented in the DATABASES setting (https://docs.djangoproject.com/en/1.9/ref/settings/#databases).There are still places in Django core code depending on a
default
database (See #13528 for example). We should hopefully get rid of them at some point, but we aren't there yet.As a workaround, did you try to set a dummy backend to the
default
alias?