From 6a8c939b1405a414fe327e30bf6f454a9af73c32 Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Tue, 16 Dec 2025 12:52:06 -0400 Subject: [PATCH 1/2] refactor: no delete from TabularInlines --- ietf/doc/admin.py | 11 +++++++---- ietf/group/admin.py | 7 ++++--- ietf/ipr/admin.py | 5 +++-- ietf/liaisons/admin.py | 5 +++-- ietf/meeting/admin.py | 9 +++++---- ietf/name/admin.py | 3 ++- ietf/person/admin.py | 3 ++- ietf/utils/admin.py | 7 +++++++ 8 files changed, 33 insertions(+), 17 deletions(-) diff --git a/ietf/doc/admin.py b/ietf/doc/admin.py index 745536f9a1e..920e389a9a3 100644 --- a/ietf/doc/admin.py +++ b/ietf/doc/admin.py @@ -15,6 +15,7 @@ ReviewAssignmentDocEvent, IanaExpertDocEvent, IRSGBallotDocEvent, DocExtResource, DocumentActionHolder, BofreqEditorDocEvent, BofreqResponsibleDocEvent, StoredObject ) +from ietf.utils.admin import SaferTabularInline from ietf.utils.validators import validate_external_resource_value class StateTypeAdmin(admin.ModelAdmin): @@ -28,17 +29,19 @@ class StateAdmin(admin.ModelAdmin): filter_horizontal = ["next_states"] admin.site.register(State, StateAdmin) -class DocAuthorInline(admin.TabularInline): +class DocAuthorInline(SaferTabularInline): model = DocumentAuthor raw_id_fields = ['person', 'email'] extra = 1 + can_delete = False + show_change_link = True -class DocActionHolderInline(admin.TabularInline): +class DocActionHolderInline(SaferTabularInline): model = DocumentActionHolder raw_id_fields = ['person'] extra = 1 -class RelatedDocumentInline(admin.TabularInline): +class RelatedDocumentInline(SaferTabularInline): model = RelatedDocument fk_name= 'source' def this(self, instance): @@ -48,7 +51,7 @@ def this(self, instance): raw_id_fields = ['target'] extra = 1 -class AdditionalUrlInLine(admin.TabularInline): +class AdditionalUrlInLine(SaferTabularInline): model = DocumentURL fields = ['tag','desc','url',] extra = 1 diff --git a/ietf/group/admin.py b/ietf/group/admin.py index fedec49d850..685c10aeea1 100644 --- a/ietf/group/admin.py +++ b/ietf/group/admin.py @@ -26,14 +26,15 @@ MilestoneGroupEvent, GroupExtResource, Appeal, AppealArtifact ) from ietf.name.models import GroupTypeName -from ietf.utils.validators import validate_external_resource_value +from ietf.utils.admin import SaferTabularInline from ietf.utils.response import permission_denied +from ietf.utils.validators import validate_external_resource_value -class RoleInline(admin.TabularInline): +class RoleInline(SaferTabularInline): model = Role raw_id_fields = ["person", "email"] -class GroupURLInline(admin.TabularInline): +class GroupURLInline(SaferTabularInline): model = GroupURL class GroupForm(forms.ModelForm): diff --git a/ietf/ipr/admin.py b/ietf/ipr/admin.py index 1a8a908dcdf..d6a320203b5 100644 --- a/ietf/ipr/admin.py +++ b/ietf/ipr/admin.py @@ -17,6 +17,7 @@ NonDocSpecificIprDisclosure, LegacyMigrationIprEvent, ) +from ietf.utils.admin import SaferTabularInline # ------------------------------------------------------ # ModelAdmins @@ -29,13 +30,13 @@ class Meta: 'sections':forms.TextInput, } -class IprDocRelInline(admin.TabularInline): +class IprDocRelInline(SaferTabularInline): model = IprDocRel form = IprDocRelAdminForm raw_id_fields = ['document'] extra = 1 -class RelatedIprInline(admin.TabularInline): +class RelatedIprInline(SaferTabularInline): model = RelatedIpr raw_id_fields = ['target'] fk_name = 'source' diff --git a/ietf/liaisons/admin.py b/ietf/liaisons/admin.py index 21515ed1a30..d873cce5362 100644 --- a/ietf/liaisons/admin.py +++ b/ietf/liaisons/admin.py @@ -7,15 +7,16 @@ from ietf.liaisons.models import ( LiaisonStatement, LiaisonStatementEvent, RelatedLiaisonStatement, LiaisonStatementAttachment ) +from ietf.utils.admin import SaferTabularInline -class RelatedLiaisonStatementInline(admin.TabularInline): +class RelatedLiaisonStatementInline(SaferTabularInline): model = RelatedLiaisonStatement fk_name = 'source' raw_id_fields = ['target'] extra = 1 -class LiaisonStatementAttachmentInline(admin.TabularInline): +class LiaisonStatementAttachmentInline(SaferTabularInline): model = LiaisonStatementAttachment raw_id_fields = ['document'] extra = 1 diff --git a/ietf/meeting/admin.py b/ietf/meeting/admin.py index d886a9a4b68..03abf5c0299 100644 --- a/ietf/meeting/admin.py +++ b/ietf/meeting/admin.py @@ -10,6 +10,7 @@ SessionPresentation, ImportantDate, SlideSubmission, SchedulingEvent, BusinessConstraint, ProceedingsMaterial, MeetingHost, Registration, RegistrationTicket, AttendanceTypeName) +from ietf.utils.admin import SaferTabularInline class UrlResourceAdmin(admin.ModelAdmin): @@ -18,7 +19,7 @@ class UrlResourceAdmin(admin.ModelAdmin): raw_id_fields = ['room', ] admin.site.register(UrlResource, UrlResourceAdmin) -class UrlResourceInline(admin.TabularInline): +class UrlResourceInline(SaferTabularInline): model = UrlResource class RoomAdmin(admin.ModelAdmin): @@ -28,7 +29,7 @@ class RoomAdmin(admin.ModelAdmin): admin.site.register(Room, RoomAdmin) -class RoomInline(admin.TabularInline): +class RoomInline(SaferTabularInline): model = Room class MeetingAdmin(admin.ModelAdmin): @@ -93,7 +94,7 @@ def name_lower(self, instance): admin.site.register(Constraint, ConstraintAdmin) -class SchedulingEventInline(admin.TabularInline): +class SchedulingEventInline(SaferTabularInline): model = SchedulingEvent raw_id_fields = ["by"] @@ -244,7 +245,7 @@ def queryset(self, request, queryset): return queryset.filter(tickets__attendance_type__slug=self.value()).distinct() return queryset -class RegistrationTicketInline(admin.TabularInline): +class RegistrationTicketInline(SaferTabularInline): model = RegistrationTicket class RegistrationAdmin(admin.ModelAdmin): diff --git a/ietf/name/admin.py b/ietf/name/admin.py index 4336e0569c7..b89d6d141cf 100644 --- a/ietf/name/admin.py +++ b/ietf/name/admin.py @@ -57,6 +57,7 @@ from ietf.stats.models import CountryAlias +from ietf.utils.admin import SaferTabularInline class NameAdmin(admin.ModelAdmin): @@ -86,7 +87,7 @@ class GroupTypeNameAdmin(NameAdmin): admin.site.register(GroupTypeName, GroupTypeNameAdmin) -class CountryAliasInline(admin.TabularInline): +class CountryAliasInline(SaferTabularInline): model = CountryAlias extra = 1 diff --git a/ietf/person/admin.py b/ietf/person/admin.py index cd8ca2abf16..be3bd17578b 100644 --- a/ietf/person/admin.py +++ b/ietf/person/admin.py @@ -7,6 +7,7 @@ from ietf.person.models import Email, Alias, Person, PersonalApiKey, PersonEvent, PersonApiKeyEvent, PersonExtResource from ietf.person.name import name_parts +from ietf.utils.admin import SaferTabularInline from ietf.utils.validators import validate_external_resource_value @@ -16,7 +17,7 @@ class EmailAdmin(simple_history.admin.SimpleHistoryAdmin): search_fields = ["address", "person__name", ] admin.site.register(Email, EmailAdmin) -class EmailInline(admin.TabularInline): +class EmailInline(SaferTabularInline): model = Email class AliasAdmin(admin.ModelAdmin): diff --git a/ietf/utils/admin.py b/ietf/utils/admin.py index 6c1c8726e10..ff464f6123f 100644 --- a/ietf/utils/admin.py +++ b/ietf/utils/admin.py @@ -51,6 +51,13 @@ def _link(self): _link.admin_order_field = ordering return _link + +class SaferTabularInline(admin.TabularInline): + """TabularInline without delete by default""" + can_delete = False # no delete button + show_change_link = True # show a link to the resource (where it can be deleted) + + from .models import DumpInfo class DumpInfoAdmin(admin.ModelAdmin): list_display = ['date', 'host', 'tz'] From 57688fdd9a7c537e0bfdf707eeb1c59177b4f3ed Mon Sep 17 00:00:00 2001 From: Jennifer Richards Date: Tue, 16 Dec 2025 12:54:21 -0400 Subject: [PATCH 2/2] refactor: no delete from StackedInlines --- ietf/person/admin.py | 4 ++-- ietf/utils/admin.py | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ietf/person/admin.py b/ietf/person/admin.py index be3bd17578b..f46edcf8aeb 100644 --- a/ietf/person/admin.py +++ b/ietf/person/admin.py @@ -7,7 +7,7 @@ from ietf.person.models import Email, Alias, Person, PersonalApiKey, PersonEvent, PersonApiKeyEvent, PersonExtResource from ietf.person.name import name_parts -from ietf.utils.admin import SaferTabularInline +from ietf.utils.admin import SaferStackedInline, SaferTabularInline from ietf.utils.validators import validate_external_resource_value @@ -26,7 +26,7 @@ class AliasAdmin(admin.ModelAdmin): raw_id_fields = ["person"] admin.site.register(Alias, AliasAdmin) -class AliasInline(admin.StackedInline): +class AliasInline(SaferStackedInline): model = Alias class PersonAdmin(simple_history.admin.SimpleHistoryAdmin): diff --git a/ietf/utils/admin.py b/ietf/utils/admin.py index ff464f6123f..e6324ad7cd7 100644 --- a/ietf/utils/admin.py +++ b/ietf/utils/admin.py @@ -52,6 +52,12 @@ def _link(self): return _link +class SaferStackedInline(admin.StackedInline): + """StackedInline without delete by default""" + can_delete = False # no delete button + show_change_link = True # show a link to the resource (where it can be deleted) + + class SaferTabularInline(admin.TabularInline): """TabularInline without delete by default""" can_delete = False # no delete button