From 3073dd98f20a0cafc9861558281ae244474641cb Mon Sep 17 00:00:00 2001 From: David Kennedy Date: Fri, 15 Dec 2023 16:26:33 -0500 Subject: [PATCH] wip --- src/registrar/admin.py | 105 ++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/src/registrar/admin.py b/src/registrar/admin.py index def7c64b1..34919fb29 100644 --- a/src/registrar/admin.py +++ b/src/registrar/admin.py @@ -1,5 +1,6 @@ import logging from django import forms +from django.db.models.functions import Concat from django.http import HttpResponse from django.shortcuts import redirect from django_fsm import get_available_FIELD_transitions @@ -11,7 +12,6 @@ from django.http.response import HttpResponseRedirect from django.urls import reverse from epplibwrapper.errors import ErrorCode, RegistryError from registrar.models.domain import Domain -from registrar.models.utility.admin_sort_fields import AdminSortFields from registrar.utility import csv_export from . import models from auditlog.models import LogEntry # type: ignore @@ -45,7 +45,35 @@ class CustomLogEntryAdmin(LogEntryAdmin): add_form_template = "admin/change_form_no_submit.html" -class AuditedAdmin(admin.ModelAdmin, AdminSortFields): +class AdminSortFields(): + + def get_queryset(db_field): + """This is a helper function for formfield_for_manytomany and formfield_for_foreignkey""" + logger.info(f"getting queryset for {db_field.name}") + # customize sorting + if db_field.name in ("other_contacts", "authorizing_official", "submitter",): + # Sort contacts by first_name, then last_name, then email + return models.Contact.objects.all().order_by(Concat("first_name","last_name","email")) + elif db_field.name in ("current_websites", "alternative_domains"): + # sort web sites + return models.Website.objects.all().order_by("website") + elif db_field.name in ("creator", "user", "investigator",): + # Sort users by first_name, then last_name, then email + return models.User.objects.all().order_by(Concat("first_name","last_name","email")) + elif db_field.name in ("domain", "approved_domain",): + # Sort domains by name + return models.Domain.objects.all().order_by("name") + elif db_field.name in ("requested_domain",): + # Sort draft domains by name + return models.DraftDomain.objects.all().order_by("name") + elif db_field.name in ("domain_application",): + # Sort domain applications by name + return models.DomainApplication.objects.all().order_by("requested_domain__name") + else: + return None + + +class AuditedAdmin(admin.ModelAdmin): """Custom admin to make auditing easier.""" def history_view(self, request, object_id, extra_context=None): @@ -57,11 +85,28 @@ class AuditedAdmin(admin.ModelAdmin, AdminSortFields): object_id=object_id, ) ) - + + def formfield_for_manytomany(self, db_field, request, **kwargs): + """customize the behavior of formfields with manytomany relationships. the customized + behavior includes sorting of objects in lists as well as customizing helper text""" + queryset = AdminSortFields.get_queryset(db_field) + if queryset: + kwargs["queryset"] = queryset + formfield = super().formfield_for_manytomany(db_field, request, **kwargs) + # customize the help text for all formfields for manytomany + formfield.help_text = ( + formfield.help_text + + " If more than one value is selected, the change/delete/view actions will be disabled." + ) + return formfield + def formfield_for_foreignkey(self, db_field, request, **kwargs): - """Used to sort dropdown fields alphabetically but can be expanded upon""" - form_field = super().formfield_for_foreignkey(db_field, request, **kwargs) - return self.form_field_order_helper(form_field, db_field) + """customize the behavior of formfields with foreign key relationships. this will customize + the behavior of selects. customized behavior includes sorting of objects in list""" + queryset = AdminSortFields.get_queryset(db_field) + if queryset: + kwargs["queryset"] = queryset + return super().formfield_for_foreignkey(db_field, request, **kwargs) class ListHeaderAdmin(AuditedAdmin): @@ -118,15 +163,6 @@ class ListHeaderAdmin(AuditedAdmin): ) return filters - # customize the help_text for all formfields for manytomany - def formfield_for_manytomany(self, db_field, request, **kwargs): - formfield = super().formfield_for_manytomany(db_field, request, **kwargs) - formfield.help_text = ( - formfield.help_text - + " If more than one value is selected, the change/delete/view actions will be disabled." - ) - return formfield - class UserContactInline(admin.StackedInline): """Edit a user's profile on the user page.""" @@ -489,13 +525,6 @@ class DomainInformationAdmin(ListHeaderAdmin): # to activate the edit/delete/view buttons filter_horizontal = ("other_contacts",) - # lists in filter_horizontal are not sorted properly, sort them - # by first_name - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name in ("other_contacts",): - kwargs["queryset"] = models.Contact.objects.all().order_by("first_name") # Sort contacts - return super().formfield_for_manytomany(db_field, request, **kwargs) - def get_readonly_fields(self, request, obj=None): """Set the read-only state on form elements. We have 1 conditions that determine which fields are read-only: @@ -634,13 +663,6 @@ class DomainApplicationAdmin(ListHeaderAdmin): filter_horizontal = ("current_websites", "alternative_domains", "other_contacts") - # lists in filter_horizontal are not sorted properly, sort them - # by website - def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name in ("current_websites", "alternative_domains"): - kwargs["queryset"] = models.Website.objects.all().order_by("website") # Sort websites - return super().formfield_for_manytomany(db_field, request, **kwargs) - # Trigger action when a fieldset is changed def save_model(self, request, obj, form, change): if obj and obj.creator.status != models.User.RESTRICTED: @@ -774,12 +796,27 @@ class DomainInformationInline(admin.StackedInline): # to activate the edit/delete/view buttons filter_horizontal = ("other_contacts",) - # lists in filter_horizontal are not sorted properly, sort them - # by first_name def formfield_for_manytomany(self, db_field, request, **kwargs): - if db_field.name in ("other_contacts",): - kwargs["queryset"] = models.Contact.objects.all().order_by("first_name") # Sort contacts - return super().formfield_for_manytomany(db_field, request, **kwargs) + """customize the behavior of formfields with manytomany relationships. the customized + behavior includes sorting of objects in lists as well as customizing helper text""" + queryset = AdminSortFields.get_queryset(db_field) + if queryset: + kwargs["queryset"] = queryset + formfield = super().formfield_for_manytomany(db_field, request, **kwargs) + # customize the help text for all formfields for manytomany + formfield.help_text = ( + formfield.help_text + + " If more than one value is selected, the change/delete/view actions will be disabled." + ) + return formfield + + def formfield_for_foreignkey(self, db_field, request, **kwargs): + """customize the behavior of formfields with foreign key relationships. this will customize + the behavior of selects. customized behavior includes sorting of objects in list""" + queryset = AdminSortFields.get_queryset(db_field) + if queryset: + kwargs["queryset"] = queryset + return super().formfield_for_foreignkey(db_field, request, **kwargs) def get_readonly_fields(self, request, obj=None): return DomainInformationAdmin.get_readonly_fields(self, request, obj=None)