Source code for app_utils.admin

"""Utilities for the admin site."""

from collections import Counter

from django.contrib import admin
from django.db.models import Count


[docs] class FieldFilterCountsMemory(admin.SimpleListFilter): """Filter by field and show counts for admin site. Counts are calculated in memory. """ field_name = "" # field to filter by def lookups(self, request, model_admin: admin.ModelAdmin): """:meta private:""" field_in_rows = model_admin.get_queryset(request).values_list( self.field_name, flat=True ) field_counts = Counter(field_in_rows) result = [ (field, f"{field} ({count:,})") for field, count in field_counts.items() ] return sorted(result, key=lambda obj: obj[0]) def queryset(self, request, queryset): """:meta private:""" if self.value(): params = {self.field_name: self.value()} return queryset.filter(**params)
[docs] class FieldFilterCountsDb(admin.SimpleListFilter): """Filter by field and show counts for admin site. Counts are calculated by the database. """ field_name = "" # field to filter by def lookups(self, request, model_admin: admin.ModelAdmin): """:meta private:""" qs = model_admin.get_queryset(request) field = qs.model._meta.get_field(self.field_name) if not field.choices: qs = qs.exclude(**{self.field_name: ""}) field_counts = ( qs.values(self.field_name) .annotate(num_words=Count(self.field_name)) .order_by(self.field_name) ) if field.choices: field_counts = self.__map_choices_field(field, field_counts) result = [ ( obj[self.field_name][0], f'{obj[self.field_name][1]} ({obj["num_words"]:,})', ) for obj in field_counts ] else: result = [ (obj[self.field_name], f'{obj[self.field_name]} ({obj["num_words"]:,})') for obj in field_counts ] return result def __map_choices_field(self, field, field_counts): """Map choices field values to corresponding labels and keep values.""" mapper = {obj[0]: obj[1] for obj in field.choices} field_counts = [ { self.field_name: (obj[self.field_name], mapper[obj[self.field_name]]), "num_words": obj["num_words"], } for obj in field_counts ] return field_counts def queryset(self, request, queryset): """:meta private:""" if self.value(): params = {self.field_name: self.value()} return queryset.filter(**params)