reset_schema.py 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. # -*- coding: utf-8 -*-
  2. """
  3. Recreates the public schema for current database (PostgreSQL only).
  4. Useful for Docker environments where you need to reset database
  5. schema while there are active connections.
  6. """
  7. from django.core.management import BaseCommand, CommandError
  8. from django.db import connections
  9. from django.conf import settings
  10. from six.moves import input
  11. class Command(BaseCommand):
  12. """`reset_schema` command implementation."""
  13. help = "Recreates the public schema for this project."
  14. def add_arguments(self, parser):
  15. super().add_arguments(parser)
  16. parser.add_argument(
  17. '--noinput', action='store_false',
  18. dest='interactive', default=True,
  19. help='Tells Django to NOT prompt the user for input of any kind.'
  20. )
  21. parser.add_argument(
  22. '-R', '--router', action='store', dest='router', default='default',
  23. help='Use this router-database instead of the one defined in settings.py'
  24. )
  25. parser.add_argument(
  26. '-S', '--schema', action='store', dest='schema', default='public',
  27. help='Drop this schema instead of "public"'
  28. )
  29. def handle(self, *args, **options):
  30. router = options['router']
  31. dbinfo = settings.DATABASES.get(router)
  32. if dbinfo is None:
  33. raise CommandError("Unknown database router %s" % router)
  34. engine = dbinfo.get('ENGINE').split('.')[-1]
  35. if engine not in ('postgresql', 'postgresql_psycopg2', 'postgis'):
  36. raise CommandError('This command can be used only with PostgreSQL databases.')
  37. database_name = dbinfo['NAME']
  38. schema = options['schema']
  39. if options['interactive']:
  40. confirm = input("""
  41. You have requested a database schema reset.
  42. This will IRREVERSIBLY DESTROY ALL data
  43. in the "{}" schema of database "{}".
  44. Are you sure you want to do this?
  45. Type 'yes' to continue, or 'no' to cancel: """.format(schema, database_name))
  46. else:
  47. confirm = 'yes'
  48. if confirm != 'yes':
  49. print("Reset cancelled.")
  50. return
  51. with connections[router].cursor() as cursor:
  52. cursor.execute("DROP SCHEMA {} CASCADE".format(schema))
  53. cursor.execute("CREATE SCHEMA {}".format(schema))