# -*- coding: utf-8 -*- from __future__ import print_function from django.core.management.base import BaseCommand from django.db import connection, transaction from django.db.models import fields from django.conf import settings settings.RELOAD_CONFIG = False import app.monkey_patch from ... import models import clip.models class Command(BaseCommand): """ sync item sort table with current settings in site.json """ help = 'alter table to match itemKeys in site.json.' args = '' def add_arguments(self, parser): parser.add_argument('--debug', action='store_true', dest='debug', default=False, help='print sql commans') def handle(self, **options): table_name = models.ItemSort._meta.db_table cursor = connection.cursor() db_rows = connection.introspection.get_table_description(cursor, table_name) db_fields = dict([(row[0], row) for row in db_rows]) db_types = dict([(row[0], connection.introspection.data_types_reverse[row[1]]) for row in db_rows]) model_fields = ['item_id'] + [f.name for f in models.ItemSort._meta.fields] rebuild = False changes = [] for name in db_types: if name not in model_fields: sql = 'ALTER TABLE "%s" DROP COLUMN "%s"' % (table_name, name) changes.append(sql) for f in models.ItemSort._meta.fields: if not f.primary_key: name = f.name col_type = f.db_type(connection) if name not in db_fields: sql = 'ALTER TABLE "%s" ADD COLUMN "%s" %s' % (table_name, name, col_type) changes.append(sql) sql = 'CREATE INDEX "%s_%s_idx" ON "%s" ("%s")' % (table_name, name, table_name, name) changes.append(sql) rebuild = True elif f.__class__.__name__ != db_types[name]: sql = 'ALTER TABLE "%s" DROP COLUMN "%s"' % (table_name, name) changes.append(sql) sql = 'ALTER TABLE "%s" ADD COLUMN "%s" %s' % (table_name, name, col_type) changes.append(sql) sql = 'CREATE INDEX "%s_%s_idx" ON "%s" ("%s")' % (table_name, name, table_name, name) changes.append(sql) rebuild = True elif db_types[name] == 'CharField' and db_fields[name][3] != f.max_length: sql = 'ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s' % (table_name, name, col_type) changes.append(sql) sql = 'ALTER TABLE "%s" ALTER COLUMN "%s" %s NOT NULL' % (table_name, name, f.null and "DROP" or "SET") changes.append(sql) rebuild = True #also update clip index table_name = clip.models.Clip._meta.db_table db_rows = connection.introspection.get_table_description(cursor, table_name) db_fields = dict([(row[0], row) for row in db_rows]) db_types = dict([(row[0], connection.introspection.data_types_reverse[row[1]]) for row in db_rows]) model_fields = ['item_id', 'sort_id'] + [f.name for f in clip.models.Clip._meta.fields] for name in db_types: if name not in model_fields: sql = 'ALTER TABLE "%s" DROP COLUMN "%s"' % (table_name, name) changes.append(sql) for f in clip.models.Clip._meta.fields: if not f.primary_key and not isinstance(f, fields.related.ForeignKey): name = f.name col_type = f.db_type(connection) if name not in db_fields: sql = 'ALTER TABLE "%s" ADD COLUMN "%s" %s' % (table_name, name, col_type) changes.append(sql) sql = 'UPDATE "%s" SET "%s"=FALSE WHERE "%s" IS NULL' % ( table_name, name, name ) changes.append(sql) sql = 'CREATE INDEX "%s_%s_idx" ON "%s" ("%s")' % (table_name, name, table_name, name) changes.append(sql) sql = 'COMMIT' changes.append(sql) sql = 'ALTER TABLE "%s" ALTER COLUMN "%s" SET NOT NULL' % (table_name, name) changes.append(sql) sql = 'BEGIN' changes.append(sql) if changes: print("Updating database schema...") for sql in changes: if options['debug']: print(sql) cursor.execute(sql) transaction.commit() if rebuild: print("Updating sort values...") ids = [i['id'] for i in models.Item.objects.all().values('id')] for id in ids: i = models.Item.objects.get(pk=id) if options['debug']: print(i) i.update_sort()