sqldsn.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. # -*- coding: utf-8 -*-
  2. """
  3. sqldns.py
  4. Prints Data Source Name on stdout
  5. """
  6. import sys
  7. from django.conf import settings
  8. from django.core.management.base import BaseCommand, CommandError
  9. from django.core.management.color import color_style
  10. class Command(BaseCommand):
  11. help = """Prints DSN on stdout, as specified in settings.py
  12. ./manage.py sqldsn [--router=<routername>] [--style=pgpass]"""
  13. requires_system_checks = False
  14. can_import_settings = True
  15. def add_arguments(self, parser):
  16. super().add_arguments(parser)
  17. parser.add_argument(
  18. '-R', '--router', action='store',
  19. dest='router', default='default',
  20. help='Use this router-database other then default'
  21. )
  22. parser.add_argument(
  23. '-s', '--style', action='store',
  24. dest='style', default=None,
  25. help='DSN format style: keyvalue, uri, pgpass, all'
  26. )
  27. parser.add_argument(
  28. '-a', '--all', action='store_true',
  29. dest='all', default=False,
  30. help='Show DSN for all database routes'
  31. )
  32. parser.add_argument(
  33. '-q', '--quiet', action='store_true',
  34. dest='quiet', default=False,
  35. help='Quiet mode only show DSN'
  36. )
  37. def handle(self, *args, **options):
  38. self.style = color_style()
  39. all_routers = options['all']
  40. if all_routers:
  41. routers = settings.DATABASES.keys()
  42. else:
  43. routers = [options['router']]
  44. for i, router in enumerate(routers):
  45. if i != 0:
  46. sys.stdout.write("\n")
  47. self.show_dsn(router, options)
  48. def show_dsn(self, router, options):
  49. dbinfo = settings.DATABASES.get(router)
  50. quiet = options['quiet']
  51. dsn_style = options['style']
  52. if dbinfo is None:
  53. raise CommandError("Unknown database router %s" % router)
  54. engine = dbinfo.get('ENGINE').split('.')[-1]
  55. dbuser = dbinfo.get('USER')
  56. dbpass = dbinfo.get('PASSWORD')
  57. dbname = dbinfo.get('NAME')
  58. dbhost = dbinfo.get('HOST')
  59. dbport = dbinfo.get('PORT')
  60. dsn = []
  61. if engine == 'mysql':
  62. dsn.append(self._mysql(dbhost, dbport, dbname, dbuser, dbpass))
  63. elif engine in ['postgresql', 'postgresql_psycopg2', 'postgis']:
  64. dsn.extend(self._postgresql(
  65. dbhost, dbport, dbname, dbuser, dbpass, dsn_style=dsn_style))
  66. elif engine == 'sqlite3':
  67. dsn.append('{}'.format(dbname))
  68. else:
  69. dsn.append(self.style.ERROR('Unknown database, can''t generate DSN'))
  70. if not quiet:
  71. sys.stdout.write(self.style.SQL_TABLE("DSN for router '%s' with engine '%s':\n" % (router, engine)))
  72. for output in dsn:
  73. sys.stdout.write("{}\n".format(output))
  74. def _mysql(self, dbhost, dbport, dbname, dbuser, dbpass):
  75. dsnstr = 'host="{0}", db="{2}", user="{3}", passwd="{4}"'
  76. if dbport is not None:
  77. dsnstr += ', port="{1}"'
  78. return dsnstr.format(dbhost, dbport, dbname, dbuser, dbpass)
  79. def _postgresql(self, dbhost, dbport, dbname, dbuser, dbpass, dsn_style=None): # noqa
  80. """PostgreSQL psycopg2 driver accepts two syntaxes
  81. Plus a string for .pgpass file
  82. """
  83. dsn = []
  84. if dsn_style is None or dsn_style == 'all' or dsn_style == 'keyvalue':
  85. dsnstr = "host='{0}' dbname='{2}' user='{3}' password='{4}'"
  86. if dbport is not None:
  87. dsnstr += " port='{1}'"
  88. dsn.append(dsnstr.format(dbhost,
  89. dbport,
  90. dbname,
  91. dbuser,
  92. dbpass,))
  93. if dsn_style == 'all' or dsn_style == 'kwargs':
  94. dsnstr = "host='{0}', database='{2}', user='{3}', password='{4}'"
  95. if dbport is not None:
  96. dsnstr += ", port='{1}'"
  97. dsn.append(dsnstr.format(dbhost,
  98. dbport,
  99. dbname,
  100. dbuser,
  101. dbpass))
  102. if dsn_style == 'all' or dsn_style == 'uri':
  103. dsnstr = "postgresql://{user}:{password}@{host}/{name}"
  104. dsn.append(dsnstr.format(
  105. host="{host}:{port}".format(host=dbhost, port=dbport) if dbport else dbhost, # noqa
  106. name=dbname, user=dbuser, password=dbpass))
  107. if dsn_style == 'all' or dsn_style == 'pgpass':
  108. dsn.append(':'.join(map(str, filter(
  109. None, [dbhost, dbport, dbname, dbuser, dbpass]))))
  110. return dsn