From 135415c98911e70710883d552761b52b65a1dc01 Mon Sep 17 00:00:00 2001 From: Rudi Matz Date: Mon, 25 May 2026 13:12:59 -0400 Subject: [PATCH] feat: make datattracker_person_id unique --- ...datatrackerperson_datatracker_id_unique.py | 26 +++++++++++++++++++ datatracker/models.py | 19 +++----------- rpc/api.py | 2 +- rpc/serializers.py | 8 +++--- 4 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 datatracker/migrations/0003_datatrackerperson_datatracker_id_unique.py diff --git a/datatracker/migrations/0003_datatrackerperson_datatracker_id_unique.py b/datatracker/migrations/0003_datatrackerperson_datatracker_id_unique.py new file mode 100644 index 000000000..f6e13e2c7 --- /dev/null +++ b/datatracker/migrations/0003_datatrackerperson_datatracker_id_unique.py @@ -0,0 +1,26 @@ +# Copyright The IETF Trust 2026, All Rights Reserved + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("datatracker", "0002_initial"), + ] + + operations = [ + migrations.AlterField( + model_name="datatrackerperson", + name="datatracker_id", + field=models.BigIntegerField( + help_text="ID of the Person in the datatracker", unique=True + ), + ), + migrations.AlterField( + model_name="historicaldatatrackerperson", + name="datatracker_id", + field=models.BigIntegerField( + db_index=True, help_text="ID of the Person in the datatracker" + ), + ), + ] diff --git a/datatracker/models.py b/datatracker/models.py index f7d33a2ae..a512210aa 100644 --- a/datatracker/models.py +++ b/datatracker/models.py @@ -10,29 +10,16 @@ class DatatrackerPersonQuerySet(models.QuerySet): - @with_rpcapi - def first_or_create( - self, defaults=None, *, rpcapi: rpcapi_client.PurpleApi, **kwargs - ): - try: - return self.get_or_create(defaults, **kwargs) - except DatatrackerPerson.MultipleObjectsReturned: - return DatatrackerPerson.objects.filter(**kwargs).first(), False - @with_rpcapi def first_or_create_by_subject_id( self, subject_id, *, rpcapi: rpcapi_client.PurpleApi ) -> tuple["DatatrackerPerson", bool]: - """Get an instance by subject id, creating it if necessary - - Like get_or_create(), but returns the first matching instance rather than - raising an exception if more than one match is found. - """ + """Get an instance by subject id, creating it if necessary.""" try: dtpers = rpcapi.get_subject_person_by_id(subject_id=subject_id) except rpcapi_client.exceptions.NotFoundException as err: raise DatatrackerPerson.DoesNotExist() from err - return self.first_or_create(datatracker_id=dtpers.id) + return self.get_or_create(datatracker_id=dtpers.id) class DatatrackerPerson(models.Model): @@ -43,7 +30,7 @@ class DatatrackerPerson(models.Model): # datatracker uses AutoField for this, which is only an IntegerField, # but might as well go big datatracker_id = models.BigIntegerField( - help_text="ID of the Person in the datatracker" + unique=True, help_text="ID of the Person in the datatracker" ) history = HistoricalRecords() diff --git a/rpc/api.py b/rpc/api.py index 86d94ecaa..c97b0614b 100644 --- a/rpc/api.py +++ b/rpc/api.py @@ -1576,7 +1576,7 @@ def perform_create(self, serializer): person_id = serializer.validated_data.pop("person_id") if person_id: with transaction.atomic(): - dt_person, _ = DatatrackerPerson.objects.first_or_create( + dt_person, _ = DatatrackerPerson.objects.get_or_create( datatracker_id=person_id, ) serializer.save( diff --git a/rpc/serializers.py b/rpc/serializers.py index 234a820da..126baa915 100644 --- a/rpc/serializers.py +++ b/rpc/serializers.py @@ -265,9 +265,7 @@ class Meta(ActionHolderSerializer.Meta): def create(self, validated_data): person_id = validated_data.pop("person_id") - dt_person, _ = DatatrackerPerson.objects.first_or_create( - datatracker_id=person_id - ) + dt_person, _ = DatatrackerPerson.objects.get_or_create(datatracker_id=person_id) return ActionHolder.objects.create( datatracker_person=dt_person, **validated_data ) @@ -2068,13 +2066,13 @@ def create(self, validated_data): "overriding_approver_person_id", None ) - approver_dt_person = DatatrackerPerson.objects.get( + approver_dt_person, _ = DatatrackerPerson.objects.get_or_create( datatracker_id=approver_person_id ) overriding_approver_dt_person = None if overriding_approver_person_id: - overriding_approver_dt_person = DatatrackerPerson.objects.get( + overriding_approver_dt_person, _ = DatatrackerPerson.objects.get_or_create( datatracker_id=overriding_approver_person_id )