Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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"
),
),
]
19 changes: 3 additions & 16 deletions datatracker/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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()

Expand Down
2 changes: 1 addition & 1 deletion rpc/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
8 changes: 3 additions & 5 deletions rpc/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
Expand Down Expand Up @@ -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
)

Expand Down