"""Backfill `VerifiedEmail` from any historical submission that already had `email_confirmed=True` (i.e. the user clicked the confirmation link before the trust list existed). One-shot; safe to re-run thanks to `update_or_create`.""" from django.db import migrations def backfill_verified_emails(apps, schema_editor): Submission = apps.get_model("submissions", "Submission") VerifiedEmail = apps.get_model("submissions", "VerifiedEmail") # `update_or_create` keeps the migration idempotent. seen: set[str] = set() qs = Submission.objects.filter(email_confirmed=True).exclude( guest_email__isnull=True ).exclude(guest_email="").values_list("guest_email", flat=True) for email in qs: email = email.strip().lower() if not email or email in seen: continue seen.add(email) VerifiedEmail.objects.update_or_create(email=email) def noop_reverse(apps, schema_editor): """We don't try to undo the backfill -- the trust list is a forward-only derived artefact; rolling back the migration leaves the rows alone.""" class Migration(migrations.Migration): dependencies = [ ("submissions", "0002_verifiedemail"), ] operations = [ migrations.RunPython(backfill_verified_emails, noop_reverse), ]