drop_test_database.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. # -*- coding: utf-8 -*-
  2. import logging
  3. from django.conf import settings
  4. from django.core.management.base import BaseCommand, CommandError
  5. from django.db.backends.base.creation import TEST_DATABASE_PREFIX
  6. from six.moves import input
  7. from django_extensions.management.mysql import parse_mysql_cnf
  8. from django_extensions.management.utils import signalcommand
  9. class Command(BaseCommand):
  10. help = "Drops test database for this project."
  11. def add_arguments(self, parser):
  12. super().add_arguments(parser)
  13. parser.add_argument(
  14. '--noinput', action='store_false', dest='interactive',
  15. default=True, help='Tells Django to NOT prompt the user for input of any kind.'
  16. )
  17. parser.add_argument(
  18. '-U', '--user', action='store', dest='user', default=None,
  19. help='Use another user for the database then defined in settings.py'
  20. )
  21. parser.add_argument(
  22. '-P', '--password', action='store', dest='password', default=None,
  23. help='Use another password for the database then defined in settings.py'
  24. )
  25. parser.add_argument(
  26. '-D', '--dbname', action='store', dest='dbname', default=None,
  27. help='Use another database name then defined in settings.py'
  28. )
  29. parser.add_argument(
  30. '-R', '--router', action='store', dest='router', default='default',
  31. help='Use this router-database other then defined in settings.py'
  32. )
  33. @signalcommand
  34. def handle(self, *args, **options):
  35. """Drop test database for this project."""
  36. router = options['router']
  37. dbinfo = settings.DATABASES.get(router)
  38. if dbinfo is None:
  39. raise CommandError("Unknown database router %s" % router)
  40. engine = dbinfo.get('ENGINE').split('.')[-1]
  41. user = password = database_name = database_host = database_port = ''
  42. if engine == 'mysql':
  43. (user, password, database_name, database_host, database_port) = parse_mysql_cnf(dbinfo)
  44. user = options['user'] or dbinfo.get('USER') or user
  45. password = options['password'] or dbinfo.get('PASSWORD') or password
  46. try:
  47. database_name = dbinfo['TEST']['NAME']
  48. except KeyError:
  49. database_name = None
  50. if database_name is None:
  51. database_name = TEST_DATABASE_PREFIX + (options['dbname'] or dbinfo.get('NAME'))
  52. if database_name is None or database_name == '':
  53. raise CommandError("You need to specify DATABASE_NAME in your Django settings file.")
  54. database_host = dbinfo.get('HOST') or database_host
  55. database_port = dbinfo.get('PORT') or database_port
  56. verbosity = options["verbosity"]
  57. if options['interactive']:
  58. confirm = input("""
  59. You have requested to drop the test database.
  60. This will IRREVERSIBLY DESTROY
  61. ALL data in the database "%s".
  62. Are you sure you want to do this?
  63. Type 'yes' to continue, or 'no' to cancel: """ % (database_name,))
  64. else:
  65. confirm = 'yes'
  66. if confirm != 'yes':
  67. print("Reset cancelled.")
  68. return
  69. if engine in ('sqlite3', 'spatialite'):
  70. import os
  71. try:
  72. logging.info("Unlinking %s database" % engine)
  73. if os.path.isfile(database_name):
  74. os.unlink(database_name)
  75. except OSError:
  76. return
  77. elif engine in ('mysql',):
  78. import MySQLdb as Database
  79. kwargs = {
  80. 'user': user,
  81. 'passwd': password,
  82. }
  83. if database_host.startswith('/'):
  84. kwargs['unix_socket'] = database_host
  85. else:
  86. kwargs['host'] = database_host
  87. if database_port:
  88. kwargs['port'] = int(database_port)
  89. connection = Database.connect(**kwargs)
  90. drop_query = 'DROP DATABASE IF EXISTS `%s`' % database_name
  91. logging.info('Executing: "' + drop_query + '"')
  92. connection.query(drop_query)
  93. elif engine in ('postgresql', 'postgresql_psycopg2', 'postgis'):
  94. import psycopg2 as Database # NOQA
  95. conn_params = {'database': 'template1'}
  96. if user:
  97. conn_params['user'] = user
  98. if password:
  99. conn_params['password'] = password
  100. if database_host:
  101. conn_params['host'] = database_host
  102. if database_port:
  103. conn_params['port'] = database_port
  104. connection = Database.connect(**conn_params)
  105. connection.set_isolation_level(0) # autocommit false
  106. cursor = connection.cursor()
  107. drop_query = "DROP DATABASE IF EXISTS \"%s\";" % database_name
  108. logging.info('Executing: "' + drop_query + '"')
  109. try:
  110. cursor.execute(drop_query)
  111. except Database.ProgrammingError as e:
  112. logging.exception("Error: %s" % str(e))
  113. return
  114. else:
  115. raise CommandError("Unknown database engine %s" % engine)
  116. if verbosity >= 2 or options['interactive']:
  117. print("Reset successful.")