# Append a 4-digit suffix to site ids that are still name-only slugs. import re import secrets from django.db import migrations, models import django.db.models.deletion from django.utils.text import slugify _HAS_SUFFIX = re.compile(r"-\d{4}$") def forwards_add_numeric_suffix(apps, schema_editor): Site = apps.get_model("farms", "Site") Kandang = apps.get_model("farms", "Kandang") PusatRegistration = apps.get_model("farms", "PusatRegistration") used = set(Site.objects.values_list("site_id", flat=True)) mapping: dict[str, str] = {} for site in Site.objects.all().order_by("site_id"): old = str(site.site_id) if _HAS_SUFFIX.search(old): continue base = slugify(str(site.site_name or "").strip())[:55] or old[:55] for _ in range(32): candidate = f"{base}-{secrets.randbelow(10_000):04d}" if candidate not in used: used.add(candidate) mapping[old] = candidate break else: raise RuntimeError(f"Could not allocate numeric site id for {old}") for old_id, new_id in mapping.items(): Kandang.objects.filter(site_id=old_id).update(site_id=new_id) PusatRegistration.objects.filter(site_id=old_id).update(site_id=new_id) Site.objects.filter(site_id=old_id).update(site_id=new_id) def noop_reverse(apps, schema_editor): raise RuntimeError("Cannot reverse site id numeric suffix migration.") class Migration(migrations.Migration): atomic = False dependencies = [ ("farms", "0017_site_slug_pk"), ] operations = [ migrations.AlterField( model_name="kandang", name="site", field=models.ForeignKey( db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name="kandangs", to="farms.site", ), ), migrations.AlterField( model_name="pusatregistration", name="site", field=models.OneToOneField( db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name="pusat_registration", to="farms.site", ), ), migrations.RunPython(forwards_add_numeric_suffix, noop_reverse), migrations.AlterField( model_name="kandang", name="site", field=models.ForeignKey( on_delete=django.db.models.deletion.CASCADE, related_name="kandangs", to="farms.site", ), ), migrations.AlterField( model_name="pusatregistration", name="site", field=models.OneToOneField( on_delete=django.db.models.deletion.CASCADE, related_name="pusat_registration", to="farms.site", ), ), ]