Opened 8 years ago

Closed 8 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 Claude Paroz, 8 years ago

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?

comment:2 by Marcin Nowak, 8 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 Tim Graham, 8 years ago

Resolution: duplicate
Status: newclosed

This looks like a duplicate of #24394 which is fixed in Django 1.9, though there still may be other issues there (#25504).

Note: See TracTickets for help on using tickets.
Back to Top