"""Admin building blocks. A service still registers its own models.""" from __future__ import annotations from django.contrib import admin, messages from django.utils.translation import gettext_lazy as _ class SourceAdminMixin: """The columns, filters and the run-now action every source list needs. ``run_task`` is the service's Celery task. It is queued rather than run inline so a slow upstream cannot hold the admin request open. """ run_task = None list_filter = ("kind", "is_enabled", "is_public", "last_status") search_fields = ("name", "slug", "description") prepopulated_fields = {"slug": ("name",)} filter_horizontal = ("tracked_satellites",) readonly_fields = ( "last_run_at", "last_status", "last_error", "success_count", "failure_count", "created_at", "updated_at", ) @admin.action(description=_("Run selected sources now")) def run_now(self, request, queryset): if self.run_task is None: # pragma: no cover - configuration error raise NotImplementedError("set run_task on the ModelAdmin") queued = 0 for src in queryset: self.run_task.delay(src.pk) queued += 1 messages.success(request, _("Queued %(n)d source(s) for fetch.") % {"n": queued}) actions = ["run_now"] class SourceRunAdminMixin: """Run history is a log: readable, filterable, never editable.""" list_display = ( "source", "started_at", "finished_at", "status", "fetched_count", "new_count", ) list_filter = ("status", "source") search_fields = ("source__name", "source__slug") readonly_fields = ( "source", "started_at", "finished_at", "status", "fetched_count", "new_count", "error", ) date_hierarchy = "started_at" def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False