mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-08-12 12:39:43 +02:00
merge main, address bulk deletion in DJA
This commit is contained in:
commit
f699c7d0b3
128 changed files with 2750 additions and 1375 deletions
|
@ -1222,9 +1222,9 @@ class ContactAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
class SeniorOfficialAdmin(ListHeaderAdmin):
|
||||
"""Custom Senior Official Admin class."""
|
||||
|
||||
search_fields = ["first_name", "last_name", "email"]
|
||||
search_fields = ["first_name", "last_name", "email", "federal_agency__agency"]
|
||||
search_help_text = "Search by first name, last name or email."
|
||||
list_display = ["first_name", "last_name", "email", "federal_agency"]
|
||||
list_display = ["federal_agency", "first_name", "last_name", "email"]
|
||||
|
||||
# this ordering effects the ordering of results
|
||||
# in autocomplete_fields for Senior Official
|
||||
|
@ -1329,6 +1329,14 @@ class UserPortfolioPermissionAdmin(ListHeaderAdmin):
|
|||
|
||||
get_roles.short_description = "Roles" # type: ignore
|
||||
|
||||
def delete_queryset(self, request, queryset):
|
||||
"""We override the delete method in the model.
|
||||
When deleting in DJA, if you select multiple items in a table using checkboxes and apply a delete action, the model
|
||||
delete does not get called. This method gets called instead.
|
||||
This override makes sure our code in the model gets executed in these situations."""
|
||||
for obj in queryset:
|
||||
obj.delete() # Calls the overridden delete method on each instance
|
||||
|
||||
|
||||
class UserDomainRoleAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
||||
"""Custom user domain role admin class."""
|
||||
|
@ -1407,10 +1415,13 @@ class BaseInvitationAdmin(ListHeaderAdmin):
|
|||
Normal flow on successful save_model on add is to redirect to changelist_view.
|
||||
If there are errors, flow is modified to instead render change form.
|
||||
"""
|
||||
# store current messages from request so that they are preserved throughout the method
|
||||
# store current messages from request in storage so that they are preserved throughout the
|
||||
# method, as some flows remove and replace all messages, and so we store here to retrieve
|
||||
# later
|
||||
storage = get_messages(request)
|
||||
# Check if there are any error or warning messages in the `messages` framework
|
||||
has_errors = any(message.level_tag in ["error", "warning"] for message in storage)
|
||||
# Check if there are any error messages in the `messages` framework
|
||||
# error messages stop the workflow; other message levels allow flow to continue as normal
|
||||
has_errors = any(message.level_tag in ["error"] for message in storage)
|
||||
|
||||
if has_errors:
|
||||
# Re-render the change form if there are errors or warnings
|
||||
|
@ -1552,13 +1563,14 @@ class DomainInvitationAdmin(BaseInvitationAdmin):
|
|||
portfolio_invitation.save()
|
||||
messages.success(request, f"{requested_email} has been invited to the organization: {domain_org}")
|
||||
|
||||
send_domain_invitation_email(
|
||||
if not send_domain_invitation_email(
|
||||
email=requested_email,
|
||||
requestor=requestor,
|
||||
domains=domain,
|
||||
is_member_of_different_org=member_of_a_different_org,
|
||||
requested_user=requested_user,
|
||||
)
|
||||
):
|
||||
messages.warning(request, "Could not send email confirmation to existing domain managers.")
|
||||
if requested_user is not None:
|
||||
# Domain Invitation creation for an existing User
|
||||
obj.retrieve()
|
||||
|
@ -1657,6 +1669,14 @@ class PortfolioInvitationAdmin(BaseInvitationAdmin):
|
|||
# Call the parent save method to save the object
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
def delete_queryset(self, request, queryset):
|
||||
"""We override the delete method in the model.
|
||||
When deleting in DJA, if you select multiple items in a table using checkboxes and apply a delete action, the model
|
||||
delete does not get called. This method gets called instead.
|
||||
This override makes sure our code in the model gets executed in these situations."""
|
||||
for obj in queryset:
|
||||
obj.delete() # Calls the overridden delete method on each instance
|
||||
|
||||
|
||||
class DomainInformationResource(resources.ModelResource):
|
||||
"""defines how each field in the referenced model should be mapped to the corresponding fields in the
|
||||
|
@ -1678,22 +1698,25 @@ class DomainInformationAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
parameter_name = "converted_generic_orgs"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
converted_generic_orgs = set()
|
||||
# Annotate the queryset to avoid Python-side iteration
|
||||
queryset = (
|
||||
DomainInformation.objects.annotate(
|
||||
converted_generic_org=Case(
|
||||
When(portfolio__organization_type__isnull=False, then="portfolio__organization_type"),
|
||||
When(portfolio__isnull=True, generic_org_type__isnull=False, then="generic_org_type"),
|
||||
default=Value(""),
|
||||
output_field=CharField(),
|
||||
)
|
||||
)
|
||||
.values_list("converted_generic_org", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
# Populate the set with tuples of (value, display value)
|
||||
for domain_info in DomainInformation.objects.all():
|
||||
converted_generic_org = domain_info.converted_generic_org_type # Actual value
|
||||
converted_generic_org_display = domain_info.converted_generic_org_type_display # Display value
|
||||
# Filter out empty results and return sorted list of unique values
|
||||
return sorted([(org, DomainRequest.OrganizationChoices.get_org_label(org)) for org in queryset if org])
|
||||
|
||||
if converted_generic_org:
|
||||
converted_generic_orgs.add((converted_generic_org, converted_generic_org_display)) # Value, Display
|
||||
|
||||
# Sort the set by display value
|
||||
return sorted(converted_generic_orgs, key=lambda x: x[1]) # x[1] is the display value
|
||||
|
||||
# Filter queryset
|
||||
def queryset(self, request, queryset):
|
||||
if self.value(): # Check if a generic org is selected in the filter
|
||||
if self.value():
|
||||
return queryset.filter(
|
||||
Q(portfolio__organization_type=self.value())
|
||||
| Q(portfolio__isnull=True, generic_org_type=self.value())
|
||||
|
@ -2031,22 +2054,25 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
parameter_name = "converted_generic_orgs"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
converted_generic_orgs = set()
|
||||
# Annotate the queryset to avoid Python-side iteration
|
||||
queryset = (
|
||||
DomainRequest.objects.annotate(
|
||||
converted_generic_org=Case(
|
||||
When(portfolio__organization_type__isnull=False, then="portfolio__organization_type"),
|
||||
When(portfolio__isnull=True, generic_org_type__isnull=False, then="generic_org_type"),
|
||||
default=Value(""),
|
||||
output_field=CharField(),
|
||||
)
|
||||
)
|
||||
.values_list("converted_generic_org", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
# Populate the set with tuples of (value, display value)
|
||||
for domain_request in DomainRequest.objects.all():
|
||||
converted_generic_org = domain_request.converted_generic_org_type # Actual value
|
||||
converted_generic_org_display = domain_request.converted_generic_org_type_display # Display value
|
||||
# Filter out empty results and return sorted list of unique values
|
||||
return sorted([(org, DomainRequest.OrganizationChoices.get_org_label(org)) for org in queryset if org])
|
||||
|
||||
if converted_generic_org:
|
||||
converted_generic_orgs.add((converted_generic_org, converted_generic_org_display)) # Value, Display
|
||||
|
||||
# Sort the set by display value
|
||||
return sorted(converted_generic_orgs, key=lambda x: x[1]) # x[1] is the display value
|
||||
|
||||
# Filter queryset
|
||||
def queryset(self, request, queryset):
|
||||
if self.value(): # Check if a generic org is selected in the filter
|
||||
if self.value():
|
||||
return queryset.filter(
|
||||
Q(portfolio__organization_type=self.value())
|
||||
| Q(portfolio__isnull=True, generic_org_type=self.value())
|
||||
|
@ -2062,24 +2088,39 @@ class DomainRequestAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
parameter_name = "converted_federal_types"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
converted_federal_types = set()
|
||||
|
||||
# Populate the set with tuples of (value, display value)
|
||||
for domain_request in DomainRequest.objects.all():
|
||||
converted_federal_type = domain_request.converted_federal_type # Actual value
|
||||
converted_federal_type_display = domain_request.converted_federal_type_display # Display value
|
||||
|
||||
if converted_federal_type:
|
||||
converted_federal_types.add(
|
||||
(converted_federal_type, converted_federal_type_display) # Value, Display
|
||||
# Annotate the queryset for efficient filtering
|
||||
queryset = (
|
||||
DomainRequest.objects.annotate(
|
||||
converted_federal_type=Case(
|
||||
When(
|
||||
portfolio__isnull=False,
|
||||
portfolio__federal_agency__federal_type__isnull=False,
|
||||
then="portfolio__federal_agency__federal_type",
|
||||
),
|
||||
When(
|
||||
portfolio__isnull=True,
|
||||
federal_agency__federal_type__isnull=False,
|
||||
then="federal_agency__federal_type",
|
||||
),
|
||||
default=Value(""),
|
||||
output_field=CharField(),
|
||||
)
|
||||
)
|
||||
.values_list("converted_federal_type", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
# Sort the set by display value
|
||||
return sorted(converted_federal_types, key=lambda x: x[1]) # x[1] is the display value
|
||||
# Filter out empty values and return sorted unique entries
|
||||
return sorted(
|
||||
[
|
||||
(federal_type, BranchChoices.get_branch_label(federal_type))
|
||||
for federal_type in queryset
|
||||
if federal_type
|
||||
]
|
||||
)
|
||||
|
||||
# Filter queryset
|
||||
def queryset(self, request, queryset):
|
||||
if self.value(): # Check if a federal type is selected in the filter
|
||||
if self.value():
|
||||
return queryset.filter(
|
||||
Q(portfolio__federal_agency__federal_type=self.value())
|
||||
| Q(portfolio__isnull=True, federal_type=self.value())
|
||||
|
@ -3226,59 +3267,86 @@ class DomainAdmin(ListHeaderAdmin, ImportExportModelAdmin):
|
|||
parameter_name = "converted_generic_orgs"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
converted_generic_orgs = set()
|
||||
# Annotate the queryset to avoid Python-side iteration
|
||||
queryset = (
|
||||
Domain.objects.annotate(
|
||||
converted_generic_org=Case(
|
||||
When(
|
||||
domain_info__isnull=False,
|
||||
domain_info__portfolio__organization_type__isnull=False,
|
||||
then="domain_info__portfolio__organization_type",
|
||||
),
|
||||
When(
|
||||
domain_info__isnull=False,
|
||||
domain_info__portfolio__isnull=True,
|
||||
domain_info__generic_org_type__isnull=False,
|
||||
then="domain_info__generic_org_type",
|
||||
),
|
||||
default=Value(""),
|
||||
output_field=CharField(),
|
||||
)
|
||||
)
|
||||
.values_list("converted_generic_org", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
# Populate the set with tuples of (value, display value)
|
||||
for domain_info in DomainInformation.objects.all():
|
||||
converted_generic_org = domain_info.converted_generic_org_type # Actual value
|
||||
converted_generic_org_display = domain_info.converted_generic_org_type_display # Display value
|
||||
# Filter out empty results and return sorted list of unique values
|
||||
return sorted([(org, DomainRequest.OrganizationChoices.get_org_label(org)) for org in queryset if org])
|
||||
|
||||
if converted_generic_org:
|
||||
converted_generic_orgs.add((converted_generic_org, converted_generic_org_display)) # Value, Display
|
||||
|
||||
# Sort the set by display value
|
||||
return sorted(converted_generic_orgs, key=lambda x: x[1]) # x[1] is the display value
|
||||
|
||||
# Filter queryset
|
||||
def queryset(self, request, queryset):
|
||||
if self.value(): # Check if a generic org is selected in the filter
|
||||
if self.value():
|
||||
return queryset.filter(
|
||||
Q(domain_info__portfolio__organization_type=self.value())
|
||||
| Q(domain_info__portfolio__isnull=True, domain_info__generic_org_type=self.value())
|
||||
)
|
||||
|
||||
return queryset
|
||||
|
||||
class FederalTypeFilter(admin.SimpleListFilter):
|
||||
"""Custom Federal Type filter that accomodates portfolio feature.
|
||||
If we have a portfolio, use the portfolio's federal type. If not, use the
|
||||
federal type in the Domain Information object."""
|
||||
organization in the Domain Request object."""
|
||||
|
||||
title = "federal type"
|
||||
parameter_name = "converted_federal_types"
|
||||
|
||||
def lookups(self, request, model_admin):
|
||||
converted_federal_types = set()
|
||||
|
||||
# Populate the set with tuples of (value, display value)
|
||||
for domain_info in DomainInformation.objects.all():
|
||||
converted_federal_type = domain_info.converted_federal_type # Actual value
|
||||
converted_federal_type_display = domain_info.converted_federal_type_display # Display value
|
||||
|
||||
if converted_federal_type:
|
||||
converted_federal_types.add(
|
||||
(converted_federal_type, converted_federal_type_display) # Value, Display
|
||||
# Annotate the queryset for efficient filtering
|
||||
queryset = (
|
||||
Domain.objects.annotate(
|
||||
converted_federal_type=Case(
|
||||
When(
|
||||
domain_info__isnull=False,
|
||||
domain_info__portfolio__isnull=False,
|
||||
then=F("domain_info__portfolio__federal_agency__federal_type"),
|
||||
),
|
||||
When(
|
||||
domain_info__isnull=False,
|
||||
domain_info__portfolio__isnull=True,
|
||||
domain_info__federal_type__isnull=False,
|
||||
then="domain_info__federal_agency__federal_type",
|
||||
),
|
||||
default=Value(""),
|
||||
output_field=CharField(),
|
||||
)
|
||||
)
|
||||
.values_list("converted_federal_type", flat=True)
|
||||
.distinct()
|
||||
)
|
||||
|
||||
# Sort the set by display value
|
||||
return sorted(converted_federal_types, key=lambda x: x[1]) # x[1] is the display value
|
||||
# Filter out empty values and return sorted unique entries
|
||||
return sorted(
|
||||
[
|
||||
(federal_type, BranchChoices.get_branch_label(federal_type))
|
||||
for federal_type in queryset
|
||||
if federal_type
|
||||
]
|
||||
)
|
||||
|
||||
# Filter queryset
|
||||
def queryset(self, request, queryset):
|
||||
if self.value(): # Check if a federal type is selected in the filter
|
||||
if self.value():
|
||||
return queryset.filter(
|
||||
Q(domain_info__portfolio__federal_agency__federal_type=self.value())
|
||||
| Q(domain_info__portfolio__isnull=True, domain_info__federal_agency__federal_type=self.value())
|
||||
Q(domain_info__portfolio__federal_type=self.value())
|
||||
| Q(domain_info__portfolio__isnull=True, domain_info__federal_type=self.value())
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue