1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
# -*- coding: utf-8 -*-
import os
try:
import urlparse
except ImportError:
import urllib.parse as urlparse
# Register database schemes in URLs.
urlparse.uses_netloc.append('postgres')
urlparse.uses_netloc.append('postgresql')
urlparse.uses_netloc.append('pgsql')
urlparse.uses_netloc.append('postgis')
urlparse.uses_netloc.append('mysql')
urlparse.uses_netloc.append('mysql2')
urlparse.uses_netloc.append('mysqlgis')
urlparse.uses_netloc.append('mysql-connector')
urlparse.uses_netloc.append('mssql')
urlparse.uses_netloc.append('spatialite')
urlparse.uses_netloc.append('sqlite')
urlparse.uses_netloc.append('oracle')
urlparse.uses_netloc.append('oraclegis')
urlparse.uses_netloc.append('redshift')
DEFAULT_ENV = 'DATABASE_URL'
SCHEMES = {
'postgres': 'django.db.backends.postgresql_psycopg2',
'postgresql': 'django.db.backends.postgresql_psycopg2',
'pgsql': 'django.db.backends.postgresql_psycopg2',
'postgis': 'django.contrib.gis.db.backends.postgis',
'mysql': 'django.db.backends.mysql',
'mysql2': 'django.db.backends.mysql',
'mysqlgis': 'django.contrib.gis.db.backends.mysql',
'mysql-connector': 'mysql.connector.django',
'mssql': 'sql_server.pyodbc',
'spatialite': 'django.contrib.gis.db.backends.spatialite',
'sqlite': 'django.db.backends.sqlite3',
'oracle': 'django.db.backends.oracle',
'oraclegis': 'django.contrib.gis.db.backends.oracle',
'redshift': 'django_redshift_backend',
}
def config(env=DEFAULT_ENV, default=None, engine=None, conn_max_age=0, ssl_require=False):
"""Returns configured DATABASE dictionary from DATABASE_URL."""
config = {}
s = os.environ.get(env, default)
if s:
config = parse(s, engine, conn_max_age, ssl_require)
return config
def parse(url, engine=None, conn_max_age=0, ssl_require=False):
"""Parses a database URL."""
if url == 'sqlite://:memory:':
# this is a special case, because if we pass this URL into
# urlparse, urlparse will choke trying to interpret "memory"
# as a port number
return {
'ENGINE': SCHEMES['sqlite'],
'NAME': ':memory:'
}
# note: no other settings are required for sqlite
# otherwise parse the url as normal
config = {}
url = urlparse.urlparse(url)
# 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)
if url.scheme == 'sqlite' and path == '':
path = ':memory:'
# Handle postgres percent-encoded paths.
hostname = url.hostname or ''
if '%2f' in hostname.lower():
# Switch to url.netloc to avoid lower cased paths
hostname = url.netloc
if "@" in hostname:
hostname = hostname.rsplit("@", 1)[1]
if ":" in hostname:
hostname = hostname.split(":", 1)[0]
hostname = hostname.replace('%2f', '/').replace('%2F', '/')
# Lookup specified engine.
engine = SCHEMES[url.scheme] if engine is None else engine
port = (str(url.port) if url.port and engine == SCHEMES['oracle']
else url.port)
# Update with environment configuration.
config.update({
'NAME': urlparse.unquote(path or ''),
'USER': urlparse.unquote(url.username or ''),
'PASSWORD': urlparse.unquote(url.password or ''),
'HOST': hostname,
'PORT': port or '',
'CONN_MAX_AGE': conn_max_age,
})
# Pass the query string into OPTIONS.
options = {}
for key, values in query.items():
if url.scheme == 'mysql' and key == 'ssl-ca':
options['ssl'] = {'ca': values[-1]}
continue
options[key] = values[-1]
if ssl_require:
options['sslmode'] = 'require'
# Support for Postgres Schema URLs
if 'currentSchema' in options and engine in (
'django.contrib.gis.db.backends.postgis',
'django.db.backends.postgresql_psycopg2',
'django_redshift_backend',
):
options['options'] = '-c search_path={0}'.format(options.pop('currentSchema'))
if options:
config['OPTIONS'] = options
if engine:
config['ENGINE'] = engine
return config
|