Source code for cw.core.admin

"""
Django admin configuration for core models.
"""

from django.contrib import admin
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _
from unfold.admin import ModelAdmin
from unfold.decorators import display

from django.utils import timezone

from .models import LLMModel, PipelineSettings, PromptTemplate


[docs] @admin.register(LLMModel) class LLMModelAdmin(ModelAdmin): list_display = [ "name", "model_id", "show_4bit", "show_active", "show_language_count", "updated_at", ] list_filter = ["is_active", "load_in_4bit"] search_fields = ["name", "model_id", "notes"] readonly_fields = ["created_at", "updated_at"] fieldsets = ( ( _("Model"), { "classes": ["tab"], "fields": ("model_id", "name", ("is_active", "load_in_4bit")), }, ), ( _("Notes"), { "classes": ["tab"], "fields": ("notes",), }, ), ( _("Metadata"), { "classes": ["tab"], "fields": ("created_at", "updated_at"), }, ), )
[docs] @display(description=_("4-bit"), boolean=True) def show_4bit(self, obj): return obj.load_in_4bit
[docs] @display(description=_("Active"), boolean=True) def show_active(self, obj): return obj.is_active
[docs] @display(description=_("Languages")) def show_language_count(self, obj): # Count languages where this is primary or alternative primary_count = obj.primary_for_languages.count() alt_count = obj.alternative_for_languages.count() total = primary_count + alt_count if total > 0: return format_html( "{} <small>({} primary, {} alt)</small>", total, primary_count, alt_count, ) return "0"
[docs] @admin.register(PromptTemplate) class PromptTemplateAdmin(ModelAdmin): """Admin interface for PromptTemplate with Unfold styling and tabs.""" list_display = [ "name", "slug", "category", "version", "is_active", "usage_count", "last_used_at", "updated_at", ] list_filter = ["category", "is_active", "created_at", "updated_at"] search_fields = ["name", "slug", "description", "template"] readonly_fields = [ "version", "created_at", "updated_at", "usage_count", "last_used_at", ] # Unfold tabs configuration - all fieldsets are tabs fieldsets = ( ( "Overview", { "fields": ("slug", "name", "category", "is_active"), "classes": ("tab",), "description": "Basic template information and status", }, ), ( "Documentation", { "fields": ("description",), "classes": ("tab",), "description": "Purpose, usage notes, and examples for this template", }, ), ( "Template Content", { "fields": ("template",), "classes": ("tab",), "description": "Jinja2 template content - use {{ variable }} syntax for placeholders", }, ), ( "Variables", { "fields": ("expected_variables",), "classes": ("tab",), "description": "Expected template variables (JSON format): {name: {type, required, description}}", }, ), ( "Version Information", { "fields": ("version", "created_by", "created_at", "updated_at"), "classes": ("tab",), "description": "Version history and authorship information", }, ), ( "Usage Analytics", { "fields": ("usage_count", "last_used_at"), "classes": ("tab",), "description": "Template usage statistics and metrics", }, ), ) actions = ["duplicate_template", "activate_version", "test_render"]
[docs] def duplicate_template(self, request, queryset): """Create draft copy for A/B testing.""" for template in queryset: template.pk = None # Force new record template.slug = f"{template.slug}-draft-{timezone.now().strftime('%Y%m%d')}" template.is_active = False template.version = 1 template.created_by = request.user template.save() self.message_user( request, f"Created {queryset.count()} draft template(s)", )
duplicate_template.short_description = "Duplicate selected templates as drafts"
[docs] def activate_version(self, request, queryset): """Set selected version as active (deactivates other versions of same slug).""" for template in queryset: # Deactivate all other versions of this slug PromptTemplate.objects.filter(slug=template.slug).update(is_active=False) # Activate this version template.is_active = True template.save(update_fields=["is_active"]) self.message_user( request, f"Activated {queryset.count()} template version(s)", )
activate_version.short_description = "Activate selected template versions"
[docs] def test_render(self, request, queryset): """Test rendering templates with sample data (basic validation).""" success_count = 0 error_count = 0 for template in queryset: try: # Test render with empty context template.render() success_count += 1 except Exception as e: error_count += 1 self.message_user( request, f"Template '{template.name}' failed to render: {e}", level="error", ) if success_count: self.message_user( request, f"{success_count} template(s) rendered successfully", )
test_render.short_description = "Test render selected templates (empty context)"
[docs] def get_queryset(self, request): """Optimize queryset with select_related for created_by.""" qs = super().get_queryset(request) return qs.select_related("created_by")
[docs] def save_model(self, request, obj, form, change): """Set created_by to current user on creation.""" if not change and not obj.created_by: obj.created_by = request.user super().save_model(request, obj, form, change)
[docs] @admin.register(PipelineSettings) class PipelineSettingsAdmin(ModelAdmin): """Singleton admin for per-node LLM model defaults.""" fieldsets = ( ( _("Global Default"), { "classes": ["tab"], "fields": ("global_default_model",), "description": "Fallback model used when no node-specific default is configured.", }, ), ( _("Research Nodes"), { "classes": ["tab"], "fields": ("concept_default_model", "culture_default_model"), }, ), ( _("Evaluation Gates"), { "classes": ["tab"], "fields": ( "format_gate_default_model", "culture_gate_default_model", "concept_gate_default_model", "brand_gate_default_model", ), }, ), ( _("Metadata"), { "classes": ["tab"], "fields": ("created_at", "updated_at"), }, ), ) readonly_fields = ["created_at", "updated_at"]
[docs] def has_add_permission(self, request): return not PipelineSettings.objects.exists()
[docs] def has_delete_permission(self, request, obj=None): return False