from django.db import migrations, models def _table_columns(schema_editor, table): connection = schema_editor.connection with connection.cursor() as cursor: return { col.name for col in connection.introspection.get_table_description(cursor, table) } def _ensure_varchar_column(schema_editor, table, column, max_length): """Add a non-null varchar column with empty default when missing; else clear NULLs.""" connection = schema_editor.connection q_table = connection.ops.quote_name(table) q_column = connection.ops.quote_name(column) if column in _table_columns(schema_editor, table): with connection.cursor() as cursor: cursor.execute( f"UPDATE {q_table} SET {q_column} = '' WHERE {q_column} IS NULL" ) return with connection.cursor() as cursor: cursor.execute( f"ALTER TABLE {q_table} " f"ADD COLUMN {q_column} varchar({max_length}) DEFAULT '' NOT NULL" ) def add_treasury_event_name(apps, schema_editor): """ Add TreasuryTxn.event_name when missing. Safe for fresh DBs and for DBs that already have the column from older deploys. """ _ensure_varchar_column(schema_editor, 'accounting_treasury_txns', 'event_name', 200) class Migration(migrations.Migration): dependencies = [ ('accounting', '0008_invoice_cancelled_status'), ] operations = [ migrations.SeparateDatabaseAndState( state_operations=[ migrations.AddField( model_name='treasurytxn', name='event_name', field=models.CharField(blank=True, default='', max_length=200), ), ], database_operations=[ migrations.RunPython(add_treasury_event_name, migrations.RunPython.noop), ], ), ]