Files
backend/api/logger/admin.py
2025-09-22 18:43:29 -06:00

149 lines
5.0 KiB
Python

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('<pre>{}</pre>', 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('<pre style="max-height: 200px; overflow-y: auto;">{}</pre>', formatted)
except:
# Si no es JSON válido, mostrar como texto
return format_html('<pre style="max-height: 200px; overflow-y: auto;">{}</pre>', 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(
'<pre style="max-height: 400px; overflow-y: auto; background: #f8f8f8; padding: 10px; border: 1px solid #ddd;">{}</pre>',
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