From 4ecda6a1ccc755877bd3119e0554143d2d99faad Mon Sep 17 00:00:00 2001 From: Kenneth Reitz Date: Tue, 2 Feb 2016 19:07:35 -0500 Subject: [PATCH] Manual merge of #59 /cc eisensheng --- dj_database_url.py | 24 +++++++++++++++++------- test_dj_database_url.py | 14 +++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/dj_database_url.py b/dj_database_url.py index e567ed4..746cfcc 100644 --- a/dj_database_url.py +++ b/dj_database_url.py @@ -71,8 +71,13 @@ def parse(url, engine=None, conn_max_age=0): url = urlparse.urlparse(url) - # Path (without leading '/'), and with no query string - path = url.path[1:].split('?')[0] + # Split query strings from path. + path = url.path[1:] + if '?' in path and not url.query: + path, query = path.split('?', 2) + else: + path, query = path, url.query + query = urlparse.parse_qs(query) # If we are using sqlite and we have no path, then assume we # want an in-memory database (this is the behaviour of sqlalchemy) @@ -94,17 +99,22 @@ def parse(url, engine=None, conn_max_age=0): 'CONN_MAX_AGE': conn_max_age, }) - # Parse the query string into OPTIONS. - qs = urlparse.parse_qs(url.query) + # Lookup specified engine. + engine = SCHEMES[url.scheme] if engine is None else engine + + # Pass the query string into OPTIONS. options = {} - for key, values in qs.items(): + for key, values in query.items(): options[key] = values[-1] + + # Support for Postgres Schema URLs + if 'currentSchema' in options and engine == 'django.db.backends.postgresql_psycopg2': + options['options'] = '-c search_path={0}'.format(options['currentSchema']) + if options: config['OPTIONS'] = options if engine: config['ENGINE'] = engine - elif url.scheme in SCHEMES: - config['ENGINE'] = SCHEMES[url.scheme] return config diff --git a/test_dj_database_url.py b/test_dj_database_url.py index 11fa512..31a7dc7 100644 --- a/test_dj_database_url.py +++ b/test_dj_database_url.py @@ -34,6 +34,18 @@ class DatabaseTestSuite(unittest.TestCase): assert url['PASSWORD'] == '' assert url['PORT'] == '' + def test_postgres_search_path_parsing(self): + url = 'postgres://uf07k1i6d8ia0v:wegauwhgeuioweg@ec2-107-21-253-135.compute-1.amazonaws.com:5431/d8r82722r2kuvn?currentSchema=otherschema' + url = dj_database_url.parse(url) + assert url['ENGINE'] == 'django.db.backends.postgresql_psycopg2' + assert url['NAME'] == 'd8r82722r2kuvn' + assert url['HOST'] == 'ec2-107-21-253-135.compute-1.amazonaws.com' + assert url['USER'] == 'uf07k1i6d8ia0v' + assert url['PASSWORD'] == 'wegauwhgeuioweg' + assert url['PORT'] == 5431 + assert url['OPTIONS']['options'] == '-c search_path=otherschema' + + def test_postgres_parsing_with_special_characters(self): url = 'postgres://%23user:%23password@ec2-107-21-253-135.compute-1.amazonaws.com:5431/%23database' url = dj_database_url.parse(url) @@ -132,7 +144,7 @@ class DatabaseTestSuite(unittest.TestCase): url = dj_database_url.config(engine=engine) assert url['ENGINE'] == engine - + def test_parse_conn_max_age_setting(self): conn_max_age = 600 url = 'mysql://bea6eb025ca0d8:69772142@us-cdbr-east.cleardb.com/heroku_97681db3eff7580?reconnect=true'