Opened 8 years ago

Last modified 2 years ago

#25947 assigned Bug

Query's str() method fails when 'default' database is empty

Reported by: liboz Owned by: Teddy Ni
Component: Database layer (models, ORM) Version: 1.9
Severity: Normal Keywords:
Cc: Egor R Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description (last modified by Tim Graham)

According to the docs, we can have

default database...[with]...parameters dictionary...blank if it will not be used.


However, when trying to print a query with something like:

print Question.objects.all().query

you get the error that

settings.DATABASES is improperly configured. Please supply the ENGINE value. 

even though the query itself can return results.

You can replicate this by creating a new project, creating a router that routes everything to a test database like so:

class Router(object):
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        return 'test'

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        return 'test'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        return True

    def allow_migrate(self, db, app_label, model=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        return True


# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASE_ROUTERS = ['test123.settings.Router']
DATABASES = {
    'default': {},
    'test': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

Create a simple model like this one:

from django.db import models

# Create your models here.
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

and run the appropriate migrations on the test database.

Then attempting to print the query will fail, but the query itself will work. I believe the error is because the sql_with_params method in django.db.models.sql.query forces the uses of the DEFAULT_DB_ALIAS:

def sql_with_params(self):
    """
    Returns the query as an SQL string and the parameters that will be
    substituted into the query.
    """
    return self.get_compiler(DEFAULT_DB_ALIAS).as_sql()

Change History (6)

comment:1 by Tim Graham, 8 years ago

Component: UncategorizedDatabase layer (models, ORM)
Description: modified (diff)
Summary: Query's str() method fails when default Database has no parametersQuery's str() method fails when 'default' database is empty
Triage Stage: UnreviewedAccepted
Type: UncategorizedBug

I guess this might be tricky to fix for reasons similar to this comment in the file: "We need to use DEFAULT_DB_ALIAS here, as QuerySet does not have (nor should it have) knowledge of which connection is going to be used."

comment:2 by liboz, 8 years ago

I looked into this a bit and Django seems to crash when running quote_name_unless_alias in django.db.models.sql.compiler because it uses DatabaseOperations' quote_name function. Could changing the DatabaseOperations for django.db.backends.dummy to have a quote_name function like that of sqlite?

I'm thinking of something like:

def quote_name(self, name):
        if name.startswith('"') and name.endswith('"'):
            return name  # Quoting once is enough.
        return '"%s"' % name

comment:3 by Egor R, 2 years ago

Cc: Egor R added

comment:4 by Teddy Ni, 2 years ago

Owner: changed from nobody to Teddy Ni
Status: newassigned

comment:5 by Teddy Ni, 2 years ago

Has patch: set

comment:6 by Mariusz Felisiak, 2 years ago

Patch needs improvement: set
Note: See TracTickets for help on using tickets.
Back to Top