from django.contrib import admin from django.utils.html import format_html from django.utils.safestring import mark_safe from .models import RequestLog, UserActivity, ErrorLog import json from config.settings import SITE_URL class ReadOnlyAdminMixin: """Mixin para hacer que los modelos sean solo lectura en el admin.""" def has_add_permission(self, request): return False def has_change_permission(self, request, obj=None): return False def has_delete_permission(self, request, obj=None): return False @admin.register(RequestLog) class RequestLogAdmin(ReadOnlyAdminMixin, admin.ModelAdmin): list_display = [ 'timestamp', 'user_display', 'method', 'path', 'status_code', 'response_time', 'ip_address' ] list_filter = [ 'method', 'status_code', 'timestamp', 'user_agent' ] search_fields = [ 'path', 'ip_address', 'user__username', 'user__email' ] readonly_fields = [ 'timestamp', 'user', 'method', 'path', 'query_params_display', 'status_code', 'response_time', 'ip_address', 'user_agent', 'body_display', 'referer' ] ordering = ['-timestamp'] date_hierarchy = 'timestamp' list_per_page = 50 def user_display(self, obj): if obj.user: return f"{obj.user.username} ({obj.user.email})" return "Anónimo" user_display.short_description = "Usuario" def query_params_display(self, obj): if obj.query_params: try: params = json.loads(obj.query_params) if isinstance(obj.query_params, str) else obj.query_params formatted = json.dumps(params, indent=2, ensure_ascii=False) return format_html('
{}
', formatted) except: return obj.query_params return "Sin parámetros" query_params_display.short_description = "Parámetros de consulta" def body_display(self, obj): if obj.body: try: # Intentar formatear como JSON si es posible body_data = json.loads(obj.body) if isinstance(obj.body, str) else obj.body formatted = json.dumps(body_data, indent=2, ensure_ascii=False) return format_html('
{}
', formatted) except: # Si no es JSON válido, mostrar como texto return format_html('
{}
', obj.body[:1000]) return "Sin body" body_display.short_description = "Cuerpo del request" @admin.register(UserActivity) class UserActivityAdmin(admin.ModelAdmin): list_display = [ 'timestamp', 'user_display', 'action', 'object_type', 'object_id', 'ip_address' ] list_filter = [ 'action', 'object_type', 'timestamp' ] search_fields = [ 'user__username', 'user__email', 'action', 'object_type', 'object_id', 'ip_address', 'description' ] readonly_fields = [ 'timestamp', 'user', 'action', 'object_type', 'object_id', 'description', 'ip_address' ] ordering = ['-timestamp'] date_hierarchy = 'timestamp' list_per_page = 50 def user_display(self, obj): if obj.user: return f"{obj.user.username} ({obj.user.email})" return "Sistema" user_display.short_description = "Usuario" @admin.register(ErrorLog) class ErrorLogAdmin(ReadOnlyAdminMixin, admin.ModelAdmin): list_display = [ 'timestamp', 'user_display', 'level', 'message_short', 'request_path' ] list_filter = [ 'level', 'timestamp' ] search_fields = [ 'user__username', 'user__email', 'level', 'message', 'request_path', 'traceback' ] readonly_fields = [ 'timestamp', 'user', 'level', 'message', 'traceback_display', 'request_path', 'ip_address' ] ordering = ['-timestamp'] date_hierarchy = 'timestamp' list_per_page = 25 def user_display(self, obj): if obj.user: return f"{obj.user.username} ({obj.user.email})" return "Sistema/Anónimo" user_display.short_description = "Usuario" def message_short(self, obj): if obj.message and len(obj.message) > 100: return f"{obj.message[:100]}..." return obj.message or "Sin mensaje" message_short.short_description = "Mensaje" def traceback_display(self, obj): if obj.traceback: return format_html( '
{}
', obj.traceback ) return "Sin traceback" traceback_display.short_description = "Stack trace" # Personalización del admin site admin.site.site_header = "EFC V2 " admin.site.site_title = "EFC V2" admin.site.index_title = "Administración del Sistema" admin.site.site_url = SITE_URL