# Generated migration for eventify_id field import secrets from django.db import migrations, models EVENTIFY_ID_CHARS = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' def generate_unique_eventify_id(existing_ids): for _ in range(100): candidate = 'EVT-' + ''.join(secrets.choice(EVENTIFY_ID_CHARS) for _ in range(8)) if candidate not in existing_ids: return candidate raise RuntimeError("Could not generate a unique Eventify ID after 100 attempts") def backfill_eventify_ids(apps, schema_editor): User = apps.get_model('accounts', 'User') existing_ids = set(User.objects.exclude(eventify_id__isnull=True).values_list('eventify_id', flat=True)) users_to_update = [] for user in User.objects.filter(eventify_id__isnull=True): new_id = generate_unique_eventify_id(existing_ids) existing_ids.add(new_id) user.eventify_id = new_id users_to_update.append(user) User.objects.bulk_update(users_to_update, ['eventify_id']) def reverse_backfill(apps, schema_editor): pass # No-op: reversing just leaves IDs set, which is fine class Migration(migrations.Migration): dependencies = [ ('accounts', '0011_user_allowed_modules_alter_user_id'), ] operations = [ # Step 1: Add the column as nullable migrations.AddField( model_name='user', name='eventify_id', field=models.CharField(blank=True, db_index=True, editable=False, max_length=12, null=True, unique=True), ), # Step 2: Backfill all existing users migrations.RunPython(backfill_eventify_ids, reverse_backfill), # Step 3: Make the field non-nullable migrations.AlterField( model_name='user', name='eventify_id', field=models.CharField(blank=False, db_index=True, editable=False, max_length=12, null=False, unique=True), ), ]