# -*- coding: utf-8 -*- """ sqldns.py Prints Data Source Name on stdout """ import sys from django.conf import settings from django.core.management.base import BaseCommand, CommandError from django.core.management.color import color_style class Command(BaseCommand): help = """Prints DSN on stdout, as specified in settings.py ./manage.py sqldsn [--router=] [--style=pgpass]""" requires_system_checks = False can_import_settings = True def add_arguments(self, parser): super().add_arguments(parser) parser.add_argument( '-R', '--router', action='store', dest='router', default='default', help='Use this router-database other then default' ) parser.add_argument( '-s', '--style', action='store', dest='style', default=None, help='DSN format style: keyvalue, uri, pgpass, all' ) parser.add_argument( '-a', '--all', action='store_true', dest='all', default=False, help='Show DSN for all database routes' ) parser.add_argument( '-q', '--quiet', action='store_true', dest='quiet', default=False, help='Quiet mode only show DSN' ) def handle(self, *args, **options): self.style = color_style() all_routers = options['all'] if all_routers: routers = settings.DATABASES.keys() else: routers = [options['router']] for i, router in enumerate(routers): if i != 0: sys.stdout.write("\n") self.show_dsn(router, options) def show_dsn(self, router, options): dbinfo = settings.DATABASES.get(router) quiet = options['quiet'] dsn_style = options['style'] if dbinfo is None: raise CommandError("Unknown database router %s" % router) engine = dbinfo.get('ENGINE').split('.')[-1] dbuser = dbinfo.get('USER') dbpass = dbinfo.get('PASSWORD') dbname = dbinfo.get('NAME') dbhost = dbinfo.get('HOST') dbport = dbinfo.get('PORT') dsn = [] if engine == 'mysql': dsn.append(self._mysql(dbhost, dbport, dbname, dbuser, dbpass)) elif engine in ['postgresql', 'postgresql_psycopg2', 'postgis']: dsn.extend(self._postgresql( dbhost, dbport, dbname, dbuser, dbpass, dsn_style=dsn_style)) elif engine == 'sqlite3': dsn.append('{}'.format(dbname)) else: dsn.append(self.style.ERROR('Unknown database, can''t generate DSN')) if not quiet: sys.stdout.write(self.style.SQL_TABLE("DSN for router '%s' with engine '%s':\n" % (router, engine))) for output in dsn: sys.stdout.write("{}\n".format(output)) def _mysql(self, dbhost, dbport, dbname, dbuser, dbpass): dsnstr = 'host="{0}", db="{2}", user="{3}", passwd="{4}"' if dbport is not None: dsnstr += ', port="{1}"' return dsnstr.format(dbhost, dbport, dbname, dbuser, dbpass) def _postgresql(self, dbhost, dbport, dbname, dbuser, dbpass, dsn_style=None): # noqa """PostgreSQL psycopg2 driver accepts two syntaxes Plus a string for .pgpass file """ dsn = [] if dsn_style is None or dsn_style == 'all' or dsn_style == 'keyvalue': dsnstr = "host='{0}' dbname='{2}' user='{3}' password='{4}'" if dbport is not None: dsnstr += " port='{1}'" dsn.append(dsnstr.format(dbhost, dbport, dbname, dbuser, dbpass,)) if dsn_style == 'all' or dsn_style == 'kwargs': dsnstr = "host='{0}', database='{2}', user='{3}', password='{4}'" if dbport is not None: dsnstr += ", port='{1}'" dsn.append(dsnstr.format(dbhost, dbport, dbname, dbuser, dbpass)) if dsn_style == 'all' or dsn_style == 'uri': dsnstr = "postgresql://{user}:{password}@{host}/{name}" dsn.append(dsnstr.format( host="{host}:{port}".format(host=dbhost, port=dbport) if dbport else dbhost, # noqa name=dbname, user=dbuser, password=dbpass)) if dsn_style == 'all' or dsn_style == 'pgpass': dsn.append(':'.join(map(str, filter( None, [dbhost, dbport, dbname, dbuser, dbpass])))) return dsn